perm filename ERRCON.MAC[IP,SYS] blob sn#725249 filedate 1983-10-01 generic text, type T, neo UTF8
TITLE ERRCON - MONITOR DETECTED ERROR HANDLING ROUTINES - V2036
SUBTTL T. HASTINGS/TH/CHW/TW/RCC/DAL	25 JUL 80
	SEARCH	F,S
	$RELOC
	$HIGH



;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1973,1974,1975,1976,1977,1978,1979,1980,1982 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VERRCN,2036	;THIS MACRO PUTS VERSION NO. IN STORAGE MAP AND GLOB

ENTRY	ERRCON		;ALWAYS LOAD ERRCON(IF LIB SEARCH)

ERRCON::
SUBTTL	CLOCK LEVEL APR ERROR HANDLING

;HERE ON PI 7 CLOCK INTERRUPT TO PROCESS APR ERRORS FOR INDIVIDUAL JOBS
;.CPAEF HOLDS COMMUNICATION FLAGS SET BY APR PI INTERRUPT LEVEL
;CALL:	MOVE	S,.CPAEF	
;	JUMPN	S,APRILM	;COME HERE IF ANYTHING HAPPENED
;	RETURN TO RESCHEDULE NEW USER

APRILM::MOVEM	S,.CPSAC##	;HERE ON ANY APR ERROR OR MEM PARITY
	SKIPN	J,.CPJOB##	;CURRENT JOB ON THIS CPU
	SETOM	.CPNJE##	;MAKE SURE NULL JOBS AC'S ARE RESTORED
	JUMPGE	S,APRIL1	;REQUEST TO SCAN MEMORY FOR PARITY OR NXM?
	TLNN	S,(CP.PSX!CP.CSX) ;YES IS THIS JUST A PRINT JOB MESSAGES REQUEST?
	JRST	APRIL2		;YES--GO LOOP THRU JOBS AND PRINT MESSAGES TO TTY'S
	PUSHJ	P,PARSWP	;NO--SWEEP CORE (AND FLAG JOBS ON KI10)
IFN FTKI10,<
	SKIPL	.CPMPC##	;ANY SERIOUS ERRORS?
	JRST	APRIL2		;NO
	PUSHJ	P,PARHL1	;YES--ANNOUNCE ON CTY AND HALT
	STOPCD	(.+1,HALT,SME)	;++SERIOUS MEMORY ERROR
	HRRZS	.CPMPC##	;TRY TO CONTINUE-PROBABLY A VERY BAD IDEA
>
APRIL2:	MOVE	J,HIGHJB##	;HIGHEST JOB NUMBER
	TRNE	S,UE.NXM	;NXM INSTEAD OF PARITY ERROR?
	JRST	NXMLOP		;YES--REPORT NXM TO ALL JOBS AFFECTED
				;NO--REPORT PARITY TO ALL JOBS AFFECTED
				; FALL INTO PARLOP
;;LOOP TO SCAN ALL JOBS, ZAP BAD ONES AND PRINT PARITY ERROR MESSAGE
PARLOP:	MOVEI	T1,JS.MPE	;MEM PARITY FOR JOB
	TDNN	T1,JBTSTS##(J)	;JOB HAVE MEM PAR IN LOW/HIGH SEG OR UPMP?
	JRST	PARLO1		;NO--KEEP LOOKING
	ANDCAM	T1,JBTSTS##(J)	;YES, CLEAR IN JOB STATUS WORD
	SKIPN	JBTADR##(J)	;IS LOW SEG STILL IN CORE? (NO IF SWAPOUT ERROR)
	JRST	PARLO1		;NO--KEEP LOOKING
	PUSHJ	P,ZAPHIM	;RETURN ALL HIS RESOURCES
	PUSHJ	P,PARSTP	;STOP JOB AND PRINT MESSAGE
PARLO1:	SOJG	J,PARLOP	;LOOP OVER ALL JOBS
IFN FTMP,<
	PUSHJ	P,GETMM##	;GET THE MM
	  JRST	.-1		;MUST WAIT
>
	PUSHJ	P,CPINXF	;FIX CORE TABLES, IF NEEDED
	  SKIPA			;CORMAX WAS DECREASED
	JRST	PARXIT		;ALL JOBS NOT ZAPPED CAN CONTINUE TO RUN
IFN FTMP,<
	PUSHJ	P,GIVMM##	;RETURN THE MM
>
;HERE IF CORMAX WAS DECREASED SO ALL JOBS MUST BE SCANNED AND ANY
; WHICH ARE TOO BIG TO BE SWAPPED IN MUST BE ZAPPED ALSO
	SETZ	J,		;FIRST CALL ARG. TO JBSTBG
PARLP2:	MOVE	T1,CORMAX##	;GET CURRENT VALUE OF CORMAX
	PUSHJ	P,JBSTBG	;SEE IF THIS JOB IS NOW TOO BIG TO RUN
	  JRST	PARXI1		;ALL JOBS HAVE BEEN LOOKED AT
	PUSHJ	P,PARSTP	;STOP THE JOB AND TELL THE USER
	JRST	PARLP2		;KEEP GOING

;EXIT FROM PARITY SWEEP AND PRINT ROUTINE
PARXIT:
IFN FTMP,<
	PUSHJ	P,GIVMM##	;RETURN THE MM
>
PARXI1:	HRROI	S,UE.PEF	;CLEAR PARITY ERROR FLAG
	ANDCAB	S,.CPAEF##	;OTHER APR ERRORS?
	JUMPN	S,APRILM	;YES, GO PROCESS THEM
	POPJ	P,		;RETURN
NXMLOP:	MOVEI	T1,JS.NXM	;JOB OVERLAPS NXM BIT
	TDNN	T1,JBTSTS##(J)	;DOES THIS JOB OVERLAP NXM?
	JRST	NXMLP1		;NO, KEEP LOOKING
	ANDCAM	T1,JBTSTS##(J)	;CLEAR THE BIT
IFN FTMONL,<
	CAME	J,MOFLPG##	;IS THIS THE JOB THAT TYPED SET MEM ON?
>
	SKIPN	JBTADR##(J)	;DOES THIS JOB HAVE CORE IN CORE?
	JRST	NXMLP1		;IF NO TO EITHER, DO NOTHING
	PUSHJ	P,ZAPUSR	;ZAP THE PROGRAM
IFN FTLOCK,<
	PUSHJ	P,UNLOCK##	;UNLOCK IT IF LOCKED
>
	PUSHJ	P,NXMSTP	;STOP THE JOB AND TELL THE USER WHAT HAPPENED
NXMLP1:	SOJG	J,NXMLOP	;LOOP OVER ALL JOBS ON THE SYSTEM
IFN FTMP,<
	PUSHJ	P,GETMM##	;GET THE MM
	  JRST	.-1		;MUST WAIT
>
	PUSHJ	P,CPINXF	;FIX CORE ALLOCATION TABLES, ETC.
	  SKIPA			;CORMAX WAS DECREASED
	JRST	NXMXIT		;ALL JOBS NOT ZAPPED CAN CONTINUE TO RUN
IFN FTMP,<
	PUSHJ	P,GIVMM##
>
;HERE IF CORMAX WAS DECREASED SO ALL JOBS MUST BE SCANNED AND ANY
; WHICH ARE TOO BIG TOO BE SWAPPED IN MUST BE ZAPPED
	MOVEI	J,0		;STARTING WITH JOB 0,
NXMLP2:	MOVE	T1,CORMAX##	; AND THE CURRENT VALUE OF CORMAX
	PUSHJ	P,JBSTBG	;SEE IF THIS JOB IS NOW TO BIG TO BE RUN
	  JRST	NXMXI1		;ALL JOBS HAVE BEEN LOOKED AT
	PUSHJ	P,NXMSTP	;STOP THE JOB AND TELL THE USER
	JRST	NXMLP2		;SEE IF ANYMORE JOBS ARE TOO BIG
NXMXIT:
IFN FTMP,<
	PUSHJ	P,GIVMM##
>
NXMXI1:	HRROI	S,UE.NXM	;CLEAR SOFTWARE NXM FLAG
	ANDCAB	S,.CPAEF##	; ..
	JUMPN	S,APRILM	;GO PROCESS OTHER ERRORS IF THEY EXIST
	POPJ	P,		;OTHERWISE, RETURN
;SUBROUTINE TO PRINT MEM PAR ERROR FOR JOB N AND STOP JOB
;CALL:	MOVE	J,JOB NO
;	PUSHJ	P,PARSTP
;	ALWAYS RETURN
PARSTP:	PUSHJ	P,SVEUB##	;MAKE JOB ADDRESSABLE
	PUSHJ	P,ZAPPGM##	;"CORE 0"
	JSP	T1,ERRPNT	;PRINT STANDARD ERROR IN JOB MESSAGE
	ASCIZ	/Memory parity error/
	JRST	NXMST1		;PRINT MESSAGE AND STOP HIM

;SUBROUTINE TO PRINT NXM ERROR FOR JOB N AND STOP JOB
NXMSTP:	PUSHJ	P,SVEUB##	;MAKE JOB ADDRESSABLE
	PUSHJ	P,ZAPPGM##	;"CORE 0"
	JSP	T1,ERRPNT	;PRINT ERROR MESSAGE FOR THE USER
	ASCIZ /Non-existent memory error/
	AOS	.CPNJA##	;COUNT NUMBER OF JOBS ZAPPED BECAUSE OF NXM
NXMST1:	MOVE	T2,.CPMPP##	;PC WHERE THE ERROR OCCURRED
	PJRST	PCPNT		;PRINT INFO FOR USER AND STOP HIM
;SUBROUTINE CALLED TO HALT CPU ON SERIOUS ERROR IN MEMORY
PARHLT::CONO	PI,PI.OFF	;NO INTERRUPTS DURING TYPEOUT
	PUSHJ	P,PARHL1	;TYPE OUT APPROPRIATE MESSAGE ON CTY
IFN FTMP,<
	SETOM	DIELOK##	;GIVE DIE LOCK BACK
>
	STOPCD	(.,HALT,FEM)	;++FATAL ERROR IN MONITOR
PARHL1:	MOVEI	T1,CTYWAT##	;NON-PI CTY TYPEOUT ROUTINE ADDRESS
	MOVEM	T1,.CPTOA##	;MAKE IT THE ONE TO USE HERE
IFN FTKL10,<
	PUSHJ	P,SVPPC##	;MAKE SURE WE'RE IN SECONDARY PROTOCOL ON KL10
>
	SKIPN	.CPREP##	;A PARITY ERROR? (NOT NXM)
	JRST	NXMCTY		;NO, NXM REPORT NXM INSTEAD
	PUSHJ	P,INLMES##	;PRINT MESSAGE TO INFORM OPER OF HALT
	ASCIZ	/
πππππ?Non-recoverable memory parity error in monitor.

[CPU Halt]

/
	POPJ	P,		;RETURN AND HALT
NXMCTY:	PUSHJ	P,INLMES##	;INFORM OPR OF HALT
	ASCIZ /
πππππ?Non-existent memory detected in monitor.

[CPU Halt]

/
	POPJ	P,		;RETURN AND HALT
;ROUTINE TO SCAN MEMORY FOR PARITY OR NXM ERRORS (APR PI OR PI 7)
;CALLED AT APR PI IF MAY BE A SERIOUS ERROR IN MONITOR AND PIS IN PROGRESS
;CALL:
;	MOVE	J,CURRENT JOB NO. ON THIS CPU
;	MOVE	S,.CPAEF SWEEP REQUEST BITS
;	PUSHJ	P,PARSWP
;	ALWAYS RETURNS - LH .CPMPC SET NEG. IF SERIOUS MONITOR PARITY
;	S PRESERVED

PARSWP::HRRZ	U,.CPCTN##	;GET CPU'S CTY LINE NUMBER
	HRRZ	U,LINTAB##(U)	;NOW GET HIS LDB
	TRNN	S,UE.PEF	;PARITY ERROR?
	JRST	NXMSWP		;NO, SWEEP FOR NXM
	MOVEI	T1,SDELIM	;GET ADDRESS OF TEXT
	PUSHJ	P,CONMES##	;PRINT START DELIMITER
	MOVEI	T1,[ASCIZ /Memory parity scan initiated by /]
	PUSHJ	P,CONMES##	;ANNOUNCE SWEEP
	PUSHJ	P,PRCHCP	;FINISH OFF MESSAGE
	SETOM	.CPREP##	;TELL REPORTERS WHICH ERROR TYPE TO REPORT
	SETOM	.CPPAA##	;YES, SET PARITY AND OF BAD ADDRESSES TO -1
	SETOM	.CPPAC##	;SET PARITY AND OF BAD CONTENTS TO -1
	SETZM	.CPPOA##	;SET PARITY OR OF BAD ADDRESSES TO 0
	SETZM	.CPPOC##	;SET PARITY OR OF BAD CONTENTS TO 0
	AOS	.CPPSC##	;INCREMENT PARITY SWEEP COUNT
	SETZM	.CPPTS##	;SET NO OF PARITIES THIS SWEEP TO 0
IFN FTKL10,<
	PUSHJ	P,SVPPC##	;DON'T LET FE TIME US OUT WHILE SWEEPING
>
	PUSHJ	P,@.CPMPS##	;CALL CPU DEPENDENT CORE SWEEP ROUTINE
	SETZM	.CPLPP##	;CLEAR LAST PARITY ERROR PC
	SKIPE	.CPPTS##	;WERE SOME BAD WORDS FOUND ON SWEEP?
	SKIPA	T1,[EDELIM]	;YES--JUST GET END DELIMITER TEXT
	MOVEI	T1,[ASCIZ /Nothing was found.
***************
/]				;NO--TELL THEM THAT
	PUSHJ	P,CONMES##	;PRINT IT
	MOVEI	T1,.ERSPR	;GET CODE FOR DAEMON
	HRL	T1,.CPSLF##	;GET CPU CDB
	PUSHJ	P,DAEEIM##	;POKE DAEMON
	SKIPE	.CPPTS##	;IF SOME REAL ERRORS WERE FOUND
	POPJ	P,		; THEN JUST RETURN NOW
	TLNN	S,(CP.PSX)	;DID PROCESSOR DETECT PARITY?
	AOSA	.CPPCS##	;NO, COUNT CHANNEL SPURIOUS COUNT
	AOSA	.CPSPE##	;YES, COUNT PROCESSOR SPURIOUS COUNT
	POPJ	P,		;RETURN - CHANNEL SPURIOUS ERROR
				;FALL INTO NEXT PAGE IF PROCESSOR SPURIOUS
IFN FTKI10,<
;HERE ON NO PARITY FOUND ON SWEEP - COULD BE READ - PAUSE - WRITE
	MOVE	T1,.CPAPC##	;MEMORY PARITY PC (STORED BEFORE SWEEP)
	TLNN	T1,(XC.USR)	;WAS PC IN USER MODE?
	HRROS	.CPMPC##	;NO, SERIOUS BECAUSE HAVE TO ASSUME
				; PARITY WAS IN MONITOR AREA - HALT FLAG
				; SO PRINT ON CTY
	MOVE	J,.CPJOB##	;CURRENT JOB # THIS CPU
	PUSHJ	P,HGHSPE##	;FLAG ALL JOBS IF HIGH SEG DOES NOT HAVE DISK COPY
				; SINCE PARITY MAY BE IN HIGH SEG, ELSE SWAP OUT ALL
				; JOBS USING HIGH SEG.
	PUSHJ	P,PARJB1	;ALWAYS FLAG CURRENT USER
				; SINCE PARITY MAY BE IN HIS JOB (READ-PAUSE-WRITE)
>;END IFN FTKI10
	POPJ	P,		;RETURN - PROCESSOR SPURIOUS ERROR

;ROUTINE TO PRINT WHO REQUESTED SCAN, WHERE, AND AT WHAT TIME
PRCHCP:	TLNN	S,(CP.PSX)	;REQUESTED BY CPU?
	JRST	PRCHC1		;NO--BY CHANNEL
	MOVEI	T1,[ASCIZ /CPU/]
	PUSHJ	P,CONMES##	;APPEND "CPU"
	MOVEI	T1,5		;START WITH CPU 5
	MOVE	T2,S		;COPY OF S
PRCHC0:	LSH	T2,-1		;NEXT CPU
	TLNN	T2,(CP.PS5←-1)	;IS IT THIS CPU?
	SOJGE	T1,PRCHC0	;NO--TRY NEXT
	PUSHJ	P,RADX10	;YES--APPEND CPU NUMBER
	JRST	PRCHC3		;CONTINUE
PRCHC1:	MOVEI	T1,[ASCIZ /channel /]
	PUSHJ	P,CONMES##	;APPEND "CHANNEL"
	MOVEI	T1,7		;START WITH CHANNEL 7
	MOVE	T2,S		;COPY OF S
PRCHC2:	LSH	T2,-1		;NEXT CHANNEL
	TLNN	T2,(CP.CS7←-1)	;IS IT THIS CHANNEL?
	SOJGE	T1,PRCHC2	;NO--TRY NEXT
	PUSHJ	P,RADX10	;YES--APPEND CHANNEL NUMBER
PRCHC3:	MOVEI	T1,[ASCIZ / on /]
	PUSHJ	P,CONMES##	;APPEND "ON"
	MOVE	T2,.CPLOG##	;SCANNING CPU'S (THIS) NAME
	PUSHJ	P,PRNAME	;APPEND IT
	MOVEI	T1,[ASCIZ / on /]
	PUSHJ	P,CONMES##	;APPEND "ON"
	PUSHJ	P,DAYTIM##	;FINISH WITH DATE AND TIME
	POPJ	P,		;RETURN
;SUBROUTINE TO SWEEP CORE LOOKING FOR NON-EXISTENT MEMORY

NXMSWP:	MOVEI	T1,SDELIM	;GET ADDRESS OF TEXT
	PUSHJ	P,CONMES##	;PRINT START DELIMITER
	MOVEI	T1,[ASCIZ /Non-existent memory scan initiated by /]
	PUSHJ	P,CONMES##	;ANNOUNCE SWEEP
	PUSHJ	P,PRCHCP	;FINISH SWEEP MESSAGE
	SETZM	.CPREP##	;SET NXM FLAG
	SETOM	.CPNAA##	;CLEAR AND OF NON-EXISTENT ADDRESSES
	SETZM	.CPNOA##	; AND OR OF NON-EXISTENT ADDRESSES
	SETZM	.CPNJA##	;NO JOBS AFFECTED YET
	AOS	.CPNSC##	;INCREMENT THE NUMBER OF NXM SWEEPS DONE
	SETZM	.CPNTS##	;CLEAR THE COUNT OF NXMS SEEN THIS SWEEP
IFN FTKL10,<
	PUSHJ	P,SVPPC##	;DON'T LET FE TIME US OUT
>
	PUSHJ	P,@.CPMPS##	;SWEEP CORE
	SETZM	.CPLPP##	;CLEAR LAST ERROR PC
	SKIPE	.CPNTS##	;ANY NON-EXISTANT MEMORY SEEN?
	SKIPA	T1,[EDELIM]	;YES--JUST GET END DELIMITER
	MOVEI	T1,[ASCIZ /Nothing was found.
***************
/]				;NO--TELL THEM THAT
	PUSHJ	P,CONMES##	;PRINT IT
	MOVEI	T1,.ERSNX	;GET DAEMON CODE
	HRL	T1,.CPSLF##	;GET CPU CDB
	PUSHJ	P,DAEEIM##	;POKE DAEMON
	SKIPE	.CPNTS##	;IF SOME REAL ERRORS WERE FOUND
	POPJ	P,		; THEN JUST RETURN NOW
	TLNE	S,(CP.PSX)	;DID THE PROCESSOR SEE THE NXM?
	AOSA	.CPSNE##	;YES, COUNT PROCESSOR SPURIOUS COUNT
	AOS	.CPNCS##	;NO, COUNT SPURIOUS CHANNEL NXMS
	POPJ	P,		;RETURN 

;DELIMITER TEXT FOR CTY SYSTEM ERROR MESSAGES
SDELIM::ASCIZ	/
ππ***************
/
EDELIM::ASCIZ	/***************
/
;SUBROUTINE TO RECORD MEM PARITY DATA FOR EACH BAD WORD
;CALL:	MOVE	T1,REL ADDR WITHIN HIGH OR LOW SEG,
;			-1 IF NEITHER IN MONITOR NOR HIGH NOR LOW SEG
;	MOVE	P1,ABS ADR OF BAD WORD (22 BITS)
;	MOVE	S,.CPAEF FLAG BITS
;	MOVE	P2,CONTENTS OF BAD WORD
;	PUSHJ	P,PARRBD	;RECORD BAD DATA
;	ALWAYS RETURN EVEN IF SERIOUS ERROR
;CALLED FROM CPU DPENDENT MEMORY SWEEP LOOP

PARRBD::TRNN	S,UE.PEF	;A PARITY ERROR?
	JRST	NXMRBD		;NO, RECORD NXM
	AOS	.CPTPE##	;INCREMENTATION NO OF MEM PARITY ERRORS FOR SYSTEM
	AOS	T2,.CPPTS##	;INCREMENT NO OF PARITY ERRORS THIS SWEEP
	SOJG	T2,PARSEC	;IS THIS THE FIRST ERROR THIS SWEEP?
	MOVEM	P1,.CPMPA##	;YES, SAVE BAD ADDRESS
	MOVEM	P2,.CPMPW##	;BAD CONTENTS
IFN FTKI10,<
	PUSH	P,T1		;SAVE T1
>
	MOVEI	T1,[ASCIZ /Parity errors detected:
/]
	PUSHJ	P,CONMES##	;ANNOUNCE ERRORS SEEN
PARSEC:	MOVEI	T1,[ASCIZ /  at /]
	PUSHJ	P,CONMES##	;PRINT "AT"
	MOVE	T1,P1		;BAD ADDRESS
	PUSHJ	P,PRTDI8	;PRINT IT
	MOVEI	T1,[ASCIZ / (phys.), Contents = /]
	PUSHJ	P,CONMES##	;PRINT MORE MESSAGE
	MOVE	T1,P2		;GET BAD CONTENTS
	PUSHJ	P,HWDPNT	;PRINT IT
IFN FTKL10,<
	MOVEI	T1,[ASCIZ /, ERA = /]
	PUSHJ	P,CONMES##	;CONTINUE MESSAGE
	MOVE	T1,.CPSTE##	;GET ERA FROM LAST SCAN TRAP
	PUSHJ	P,HWDPNT	;PRINT IT
>
	PUSHJ	P,CRLF##	;END WITH CRLF
	ANDM	P1,.CPPAA##	;ACCUM AND OF BAD ADDRESSES THIS SWEEP
	ANDM	P2,.CPPAC##	;ACCUM AND OF BAD CONTENTS THIS SWEEP
	IORM	P1,.CPPOA##	;ACCUM OR OF BAD ADDRESSES THIS SWEEP
	IORM	P2,.CPPOC##	;ACCUM OR OF BAD CONTENTS THIS SWEEP
	MOVE	T2,.CPPTS##	;PARITY ERRORS FOUND ON CURRENT SCAN
	CAIG	T2,M.CBAT##	;IS THERE ROOM FOR THIS BAD ADR IN TABLE?
	MOVEM	P1,.CPBAT##-1(T2) ;YES, STORE IN I-TH POSITION IN CDB
	MOVEM	P1,.CPLPA##	;ALWAYS STORE LAST PARITY ADDRESS
IFN FTKL10!FTKS10,<
	POPJ	P,		;RETURN
>
				;NEXT PAGE FOR KI10'S
IFN FTKI10,<
	POP	P,T1		;RESTORE T1
	JUMPE	T1,CPOPJ##	;IF ADDR NOT IN MONITOR OR A JOB, JUST RETURN
PARSC1:	JUMPN	J,PARJHS	;WAS ERROR IN A JOB AND NOT MONITOR?
	HRROS	.CPMPC##	;NO, FLAG AS SERIOUS ERROR - MUST HALT AFTER PRINT
	POPJ	P,		;RETURN (CURRENT JOB ALREADY FLAGGED TO STOP)
;HERE IF BAD JOB OR HIGH SEG - T1 STILL HAS REL. ADR. WITHIN SEG
PARJHS:	JUMPL	J,PARJOB	;FLAG JOB BAD IF IN UPMP
	CAILE	J,JOBMAX##	;IS PARITY ERROR IN LOW SEGMENT?
	PJRST	HGHPAR##	;NO, GO FIND ALL JOBS USING THIS HIGH SEG
				; AND CALL PARJOB FOR EACH ONE WHICH DOESN'T HAVE
				; HIGH SEG DISK COPY
	PJRST	PARJOB		;GO FLAG JOB
>;END IFN FTKI10
;HERE TO RECORD NON-EXISTANT MEMORY FOUND ON THE SWEEP

NXMRBD:	AOS	.CPTNE##	;COUNT TOTAL NUMBER OF NXMS SEEN
	AOS	T2,.CPNTS##	;COUNT UP THE NUMBER SEEN THIS SWEEP
	SOJG	T2,NXMSEC	;JUMP IF NOT THE FIRST NXM THIS SWEEP
	MOVEM	P1,.CPMNA##	;FIRST THIS SWEEP, RECORD BAD ADDRESS
	PUSH	P,T1		;SAVE T1
	MOVEI	T1,[ASCIZ /Non-existent memory detected:
/]
	PUSHJ	P,CONMES##	;ANNOUNCE ERRORS
NXMSEC:	MOVEI	T1,[ASCIZ /  at /]
	PUSHJ	P,CONMES##	;PRINT "AT"
	MOVE	T1,P1		;GET BAD ADDRESS
	PUSHJ	P,PRTDI8	;PRINT IT
	MOVEI	T1,[ASCIZ / (phys.)
/]
	PUSHJ	P,CONMES##	;FINISH MESSAGE
	ANDM	P1,.CPNAA##	;AND OF BAD ADDRESSES
	IORM	P1,.CPNOA##	;OR OF BAD ADDRESSES
	MOVE	T2,.CPNTS##	;NUMBER OF NXM'S SEEN ON CURRENT SCAN
	CAIG	T2,M.CBAT##	;HAVE THE MAXIMUM NUMBER OF BAD ADDRESSES BEEN STORED?
	MOVEM	P1,.CPBAT##-1(T2) ;NO, STORE THIS ONE
	MOVEM	P1,.CPLNA##	;ALWAYS STORE THE LAST BAD ADDRESS
	MOVE	T1,P1		;BAD ADDRESS TO T1
	LSH	T1,W2PLSH##	;CONVERT TO BAD PAGE
	IDIVI	T1,↑D36		;36 BITS/WORD
	MOVE	T2,BITTBL##(T2)	;BIT POSITION WITHIN THE WORD
	IORM	T2,NXMTAB##(T1)	;MARK THIS PAGE AS NON-EXISTANT
	POP	P,T1		;RESTORE T1
	JUMPE	T1,CPOPJ##	;RETURN IF BAD ADDRESS NOT IN THE MONITOR OR A JOB
	JUMPN	J,NXMJHS	;JUMP IF BAD ADDRESS IN SOME SEGMENT
	HRROS	.CPMPC##	;BAD ADDRESS IS IN THE MONITOR,
				; FLAG THIS AS A SERIOUS ERROR
	POPJ	P,		;AND CONTINUE THE SWEEP
NXMJHS:	JUMPL	J,NXMJH2	;FLAG JOB IF IN UPMP
	CAILE	J,JOBMAX##	;BAD ADDRESS IN A HIGH SEGMENT?
	PJRST	HGHPAR##	;YES, FLAG HIGH SEGMENT AS IN NXM
NXMJH2:	MOVEI	T1,JS.NXM	;BAD ADDRESS IN A LOW SEGMENT, FLAG
	IORM	T1,JBTSTS##(J)	; THE JOB TO BE STOPPED
	POPJ	P,		;AND RETURN TO CONTINUE THE SWEEP
;SUBROUTINE TO FLAG JOB FOR MESSAGE - IF APR DETECTED (RATHER THAN CHANNEL)
;CALL:	MOVE	J,JOB NUMBER
;	MOVE	S.CPAEF	;CPU OR CHAN DETECTED PARITY
;	PUSHJ	P,PARJOB
;	ALWAYS RETURN
;CALLED ON CPU0 AND CPU1

PARJOB:	TLNN	S,(CP.PSX)	;PARITY FOUND BY ANY PROCESSOR?
	POPJ	P,		;NO, RETURN
				;YES, FALL INTO PARJB1
;SUBROUTINE TO FLAG JOB FOR MEM PAR MESSAGE - ALWAYS
;CALL:	MOVE	J,JOB NUMBER
;	PUSHJ	P,PARJB1
;	ALWAYS RETURN

PARJB1::MOVSI	T1,JACCT	;CLEAR JACCT SO THAT DAMAGED PROGRAM
	ANDCAM	T1,JBTSTS##(J)	; WILL NOT HAVE PRIVILEGES
	MOVEI	T1,JS.MPE	;MEMORY PARITY ERROR IN JOB FLAG
	IORM	T1,JBTSTS##(J)	;SET JOB STATUS WORD
	POPJ	P,		;RETURN

;SUBROUTINE TO RETURN ALL JOBS WHICH ARE OR WOULD BE TOO BIG TO RUN
; IF MEMORY HAS DROPPED OFF LINE OR WERE TO BE SET OFF LINE
;CALLING SEQUENCE:
;	MOVE	T1,NEW VALUE OF CORMAX
;	MOVEI	J,0	;FIRST CALL
;	PUSHJ	P,JBSTBG
;RETURN CPOPJ IF NO JOB OR NONE OF THE REMAINING JOBS ARE TOO BIG, CPOPJ1
; IF A JOB IS TOO BIG, J = JOB NUMBER OF THE JOB WHICH IS TOO BIG

JBSTBG::PUSH	P,T1		;SAVE THE NEW VALUE OF CORMAX
JBSTB1:	ADDI	J,1		;LOOK AT THE NEXT JOB
	CAMLE	J,HIGHJB##	;LOOKED AT ALL JOBS?
	JRST	TPOPJ##		;YES, GIVE ALL DONE RETURN
	PUSHJ	P,SEGSIZ##	;SIZE OF THIS JOBS LOW SEGMENT
	MOVE	T1,T2		;SAVE THAT
	PUSH	P,J		;SAVE THE JOB NUMBER
	MOVEI	T2,0		;ASSUME THAT THE JOB DOESN'T HAVE A HIGH SEGMENT
	SKIPLE	J,JBTSGN##(J)	;DOES IT?
	PUSHJ	P,SEGSIZ##	;YES, GET THE SIZE OF THE HIGH SEGMENT
	POP	P,J		;RESTORE THE JOB NUMBER
	ADD	T1,T2		;SIZE OF THE JOB IN PAGES
	LSH	T1,P2WLSH##	;SIZE OF THE JOB IN WORDS
	CAMLE	T1,(P)		;IS THE JOB TOO BIG TO CONTINUE TO RUN?
	JRST	TPOPJ1##	;YES, SKIP RETURN TO CALLER
	JRST	JBSTB1		;NO, LOOK AT THE NEXT JOB
;HERE IF NO MEM PARITY - MUST BE APR ERROR
APRIL1:	SETZM	.CPAEF##	;CLEAR APR ERROR FLAG (IN CASE OTHER APR ERRORS
				; OCCUR BEFORE EXIT THIS CODE)
	MOVE	T1,.CPAPC##	;ERROR PC STORED BY APR PI LEVEL
				; (REAL PC MAY HAVE BEEN ZEROED TO DISMISS INT)
	MOVEM	T1,.CPPC##	;STORE IN CURRENT USER PROTECTED PC
				; (SO DUMP WILL KNOW REAL PC)
IFN FTCCIN!FTDAEM,<
	MOVEM	T1,.JDAT+JOBPD1##  ;STORE FOR POSSIBLE .JBINT
>
	TRNE	S,AP.PPV	;PROPRIETARY VIOLATION?
	JRST	APRPPV		;YES
	TRNN	S,AP.ILM	;ILLEGAL MEMORY?
	JRST	APRNXM		;NO
IFN FTPI,<
	SIGNAL	C$IMR		;SIGNAL ILL MEM REF CONDITION
	  SKIPA			;USER DOESN'T WANT TRAP
	POPJ	P,		;WANTS INTERCEPT GO TO USER
>
	HRRZ	T1,.CPAPC##	;PC STORED BY APR INTERRUPT
	CAMLE	T1,.CPREL##	;IS PC IN BOUNDS(LOW SEG)?
	PUSHJ	P,SEGILM##	;NO, IS PC IN LEGAL MEMORY IN HIGH SEG?
	JRST	APRILR		;YES, GO PRINT ILL MEM REF
	JSP	T1,ERRPTU	;NO, PRINT PC EXCEEDS MEM BOUND
	ASCIZ	/PC out of bounds/
	JRST	APRSCD		;PRINT LOC, THEN STOP JOB

APRILR:	JSP	T1,ERRPTU
	ASCIZ	/Illegal memory reference/
	JRST	APRSCD		;PRINT LOC, THEN STOP JOB
APRNXM:	TRNN	S,AP.NXM	;NON-EX MEM?
	JRST	APRPDL		;NO
IFN FTPI,<
	SIGNAL	C$NXM		;SIGNAL JOB
	  SKIPA			;NOT INTERRESTED
	POPJ	P,		;TRAP TO USER
> ;END FTPI
	SKIPE	J,.CPJOB##	;JOB RUNNING WHEN NXM HAPPENED
	PUSHJ	P,GIVRES	;RETURN RESOURCES, ETC.
	JSP	T1,ERRPTU	;YES
NXMMES::ASCIZ	/Non-existent memory/
	JRST	APRSCD		;PRINT LOC, THEN STOP JOB
APRPPV:	JSP	T1,ERRPTU
	ASCIZ	/Proprietary violation/
	JRST	APRSCD
;SUBROUTINE TO PRINT JOB NUMBER AND PROG NAME ON OPR
;CALL:	MOVEI	T1,JOB STATUS BIT (JS.MPE OR JS.DPM)
;	MOVE	U,LINE DATA BLOCK FOR CTY OR OPR
;	PUSHJ	P,OPRPJN	;PRINT JOB NUMBERS
;	ALWAYS RETURN

OPRPJN:	PUSH	P,T1		;SAVE JOB STATUS BIT TO TEST FOR MESSAGE
	PUSHJ	P,INLMES##	;TELL HIM JOB NOS. SO HE WILL RESTART
				; SYSTEM JOBS IF THEY HAVE PROBLEM
	ASCIZ	/ for job/
	MOVE	J,HIGHJB##	;HIGHEST JOB NUMBER
;LOOP TO PRINT JOB NOS. AND PROGRAM NAME OF ALL JOBS WITH BAD PARITY
; OR DAEMON PROBLEM MESS
PARLP1:	MOVE	T1,JBTSTS##(J)	;JOB STATUS WORD
	TDNE	T1,(P)		;DOES THIS JOB HAVE BAD PARITY OR DAEMON
				; PROBLEM? (DEPENDING ON CALLERS ARG)
	PUSHJ	P,PRJBNM	;YES, PRINT JOB# AND PROGRAM NAME
	SOJG	J,PARLP1	;ANY MORE JOBS?
	POP	P,T1		;RESTORE STACK
	PJRST	CRLF##		;NO, PRINT CRLF AND RETURN

;SUBROUTINE TO PRINT SWAP OUT MEM PAR ERROR
;CALL:	MOVE	J,JOB USING HIGH SEG (WHETHER IN CORE OR NOT)
;	PUSHJ	P,SWOMES
;	ALWAYS RETURN JOB SWAPPED, DAEMON CALLED

SWOMES::MOVSI	T1,JERR		;SET JERR SO WE DO NOT
	IORM	T1,JBTSTS##(J)	;TRY TO INTERCEPT
	JSP	T1,ERRPNT	;PRINT MESSAGE
	ASCIZ	/Swap out channel memory parity error/
	PJRST	APRSCD		;PRINT PC AND STOP JOB

;SUBROUTINE TO PRINT <SPACE> JOB NO. [PROG. NAME]
;CALL:
;	MOVE	J,JOB NUMBER
;	MOVE	U,LDB FOR OPR OR CTY
;	PUSHJ	P,PRJBNM		;PRINT JOB NO. AND PROG. NAME
;	ALWAYS RETURN
PRJBNM::PUSHJ	P,PRSPC##	;YES, PRINT LEADING SPACE
	MOVE	T1,J		;PRINT JOB NO.
	PUSHJ	P,RADX10	;AS DECIMAL
	PUSHJ	P,PRLBK##	;PRINT LEFT BRACKET
	MOVE	T2,JBTPRG##(J)	;PROGRAM NAME
	PUSHJ	P,PRNAME	;PRINT SO OPER WILL RECOGNIZE HIS JOBS
	PUSHJ	P,PRRBK##	;PRINT RIGHT BRACKET
	POPJ	P,		;RETURN
;SUBROUTINE TO CHECK IF JOB HAS BEEN WAITING FOR TWO SUCCESSIVE
; MINUTE CHECKS FOR DAEMON.  CALLED ONCE A MINUTE FOR EACH JOB
;CALL:	MOVE	J,JOB NUMBER
;	PUSHJ	P,DPMJOB
;	  YES	RETURN - MESSAGE PRINTED ON JOB CONSOLE
;	NO RETURN

IFN FTDAEM,<			;DAEMON FEATURE?
DPMJOB::MOVE	T1,JBTSTS##(J)	;JOB STATUS WORD
	TRNN	T1,JS.DPM	;THIS JOB BEEN WAITING FOR 2 CONSECUTIVE MIN?
	JRST	CPOPJ1##	;NO
	PUSHJ	P,STDAEM##	;START DAEMON
	  PJRST	DAEDON##	;NO DAEMON
	PUSHJ	P,TTYFND##	;YES, FIND CONTROLLING TTY
	JUMPE	U,CPOPJ##
	PUSHJ	P,DAEPRB	;PRINT PROBLEM WITH DAEMON
	PUSHJ	P,INLMES##	;TELL USER WHAT SYSTEM IS DOING ABOUT IT
	ASCIZ	/, operator action requested
/
	PJRST	TTYSTR##	;START TTY

;SUBROUTINE TO PRINT ON OPR PROBLEM WITH DAEMON
;CALLED ONCE A MIN ONLY IF A JOB IS STILL WAITING
;CALL:	PUSHJ	P,DPMOPR

DPMOPR::HRRZ	U,OPRLDB##	;OPR LINE DATA BLOCK HDR
	PUSHJ	P,DAEPRB	;PRINT PROBLEM WITH DAEMON
	MOVEI	T1,JS.DPM	;JOB STATUS BIT - NEED DAEMON PROB MESS.
	PJRST	OPRPJN		;TELL OPR WHICH JOBS ARE STUCK

;SUBROUTINE TO PRINT PROBLEM WITH DAEMON
;CALL:	MOVE	U,LINE DATA BLOCK ADR
;	PUSHJ	P,DAEPRB

DAEPRB:	PJSP	T1,CONMES##	;PRINT MESSAGE AND RETURN
	ASCIZ	/
%Problem with DAEMON/
>				;END DAEMON FEATURE
APRPDL:	TRNN	S,AP.POV	;PUSHDOWN OVERFLOW?
	JRST	APRLTH		;NO
	TLNE	T1,USRMOD	;IS PUSHDOWN LIST OVERFLOW IN EXEC UUO?
	JRST	PRTPOV		;NO - PRINT USER ERROR MESSAGE
	STOPCD	PRTPV1,DEBUG,EPO,	;++EXEC PDL OV


PRTPV1:	AOS	EPOCNT##	;NO OF NON-RECOVERABLE MONITOR PDL OVFS
	MOVE	J,.CPJOB##		;ZAPUSR REQUIRES J SET UP
	PUSHJ	P,ZAPUSR	;CLEAR ALL DDB'S, CHANS
	JRST	PRTPV2


APRLTH:	TRNN	S,XP.LTH	;LOOP IN TRAP HANDLER?
	STOPCD	CPOPJ##,DEBUG,SAC, ;++STRANGE APR CONDITION
	JSP	T1,ERRPTU	;TYPE MESSAGE
	ASCIZ/Loop in trap handler/
	JRST	APRSCD		;AND PC OF ERROR

PRTPOV:
IFN FTPI,<
	SIGNAL	C$PLOV		;SEE IF USER CARES
	  SKIPA			;DOESN'T
	POPJ	P,		;HE DOES
>
PRTPV2:	JSP	T1,ERRPTU	;PRINT ERROR MESSAGE
PDLMES::ASCIZ	/Push down list overflow/
APRSCD:	MOVE	T2,.CPAPC##	;PRINT APR PC 
	JRST	PCPNT		;AS:
				; 1)"AT USER LOC XXX" OR
				; 2)"AT EXEC LOC XXX; EXEC CALLED FROM
				; EXEC/USER LOC YYY
;ADDRESS CHECK ERROR AT ANY LEVEL
;F MUST BE SET UP TO POINT TO OFFENDING DEVICE


ADRERR::
IFN FTPI,<
	LDB	J,PJOBN##	;OFFENDING JOB'S JOB NUMBER
	SIGNAL	C$ADCK		;SEE IF USER ENABLED FOR ADDRESS CHECK
	  SKIPA			;USER DOESN'T WANT TRAP
	JRST	ERRGOU		;GO TO USER
>
	JSP	T1,ERRDEV	;GET JOB NO. FROM DEVICE DATA BLOCK
	ASCIZ	/Address check for /
	JRST	DEVEXC		;PRINT "DEVICE XXX; EXEC CALLED FROM
				; EXEC/USER LOC YYY"
				; THEN STOP JOB
;SUBROUTINE TO CLEAR ALL DDB'S, IO CHARS
;CALL WITH JOB NUMBER IN J
ZAPHIM:	PUSHJ	P,SVEUB##	;MAKE HIM ADDRESSABLE
ZAPHER::PUSHJ	P,SWPCLN##	;ZAP THE ACCESS TABLES
	PUSHJ	P,GIVRSC	;GIVE UP RESOURCES
	PJRST	ZAPUSC		;PITCH INITED DDB'S
ZAPUSR::JUMPE	J,CPOPJ##
	PUSHJ	P,GIVRSC	;GIVE UP ANY RESOURCES JOB MAY HAVE
	CAMN	J,.CPJOB##	;CURRENT JOB?
	POPJ	P,		;YES, GIVE UP INITED DDB'S ON RESET
				; (ALL SHARED RESOURCES ALREADY GIVEN UP)
ZAPUSC::HLRZ	F,DEVLST##	;LOC OF FIRST DDB
ZAPUS2:	LDB	T1,PJOBN##	;OWNER OF DDB
	MOVEI	T2,DEPMSG	;IS THIS DDB CONTROLLED BY MPX
	TDNN	T2,DEVMSG(F)	;IF SO, GIVE IT UP WHEN WE ZAP MPX
	CAME	T1,J		;RIGHT GUY OWN IT
	SKIPA			;NO, DON'T RELEASE IT
	PUSHJ	P,RELEA9##	;YES, RELEASE IT
	JUMPE	F,ZAPUSC	;F=0 IF NETWORK DDB WAS RELEASED
	HLRZ	F,DEVSER(F)
	JUMPN	F,ZAPUS2
	POPJ	P,		;RETURN

;SUBROUTINE TO RESET A JOB WHOSE ASSOCIATED
;HISEG HAD A SWAP INPUT ERROR

ZAPHGH::SKIPN	JBTADR##(J)
	POPJ	P,
	PUSHJ	P,CLRJOB##
	PUSHJ	P,ZAPUSR
	PJRST	ERRSWP
;SUBROUTINE TO RETURN ALL RESOURCES
;CALL WITH J=JOB#
GIVRES::NTGIVE			;RETURN THE NETWORK INTERLOCK
	JUMPE	J,CPOPJ##
	CAMN	J,.CPJOB##	;NO DEVICES ACTIVE IF NOT CURRENT JOB
	PUSHJ	P,IOWAIT##	;WAIT FOR ANY ACTIVE DEVICES TO FINISH
GIVRSC::HLRZ	F,SWPDDB##+DEVSER ;START AT FIRST DSK
GIVRS0:	MOVE	T1,DEVMOD(F)	;IS THIS A DISK?
	TLNN	T1,DVDSK
IFN FTSPL,<
	SKIPGE	DEVSPL(F)	;NO, SPOOLED DDB?
	CAIA			;YES
>
	JRST	GIVRS3		;NO
	MOVE	S,DEVIOS(F)
	LDB	T1,PJOBN##	;YES, THIS JOB OWN IT?
	CAMN	T1,J
	PUSHJ	P,RETRES##	;YES, RETURN ANY RESOURCES IT OWNS
GIVRS3:	PUSHJ	P,NXDDB##	;AND TRY NEXT DDB
	  JRST	[JUMPE F,GIVRS1 ;DONE IF 0
		 CAMN J,.UPMP+.UPJOB
		 JRST GIVRS0	;CONTINUE IF JOB IS ADDRESSABLE
		 JRST GIVRS1]	;NEXT ADDRESSABLE - DONE
	JRST	GIVRS0		;TRY NEXT
GIVRS1:	SETZ	T1,		;START WITH FIRST RESOURCE
	DPB	T1,PJBSTS##	;MAKE SURE THAT JOB DOESN'T APPEAR
				; TO HAVE ACTIVE DISK I/O
GIVRS2:	CAMN	J,USRTAB##(T1)	;OWNED BY JOB?
	PUSHJ	P,DVFREE##(T1)	;YES--FREE IT UP
	CAIGE	T1,AVLNUM##	;DONE YET?
	AOJA	T1,GIVRS2	;NO--CONTINUE
	PUSHJ	P,ADFREE##	;RETURN AU,DA IF OWNED
	PUSHJ	P,TPFREE##	;FREE UP TAPE KONTROLLERS
IFN FTKL10,<
	PUSHJ	P,GIVPMR##	;DOES THIS JOB HAVE THE PERFORMANCE METER?
				;NO, SO DON'T GIVE IT UP.
				;YES, GIVE IT BACK SO OTHERS MAY MEASURE
>;END IFN FTKL10
IFN	FTLOCK,<
	PUSHJ	P,UNLOCK##	;UNLOCK THE JOB IF LOCKED
>
	PUSH	P,W		;SAVE W
	PUSHJ	P,FNDPDB##	;FIND JOBS PDB
	 JRST	WPOPJ##		;RETURN IF NONE
	SKIPLE	.PDDVL##(W)	;ANY LOGICAL NAMES AROUND
	PUSHJ	P,SETDVF##	;YES,BLAST THEM
	JRST	WPOPJ##		;RESTORE W AND RETURN
NPDUFL::STOPCD	.,STOP,NPU,	;++NULL PUSH-DOWN-LIST UNDERFLOW

;JSR TO HERE FROM INTRPT LOC
	$LOW
PIERR::0
	EXCH	P,PIEPDL
	STOPCD	.,CPU,PIE,	;++PRIORITY INTERRUPT ERROR
PIEPDL::XWD	0,.
	BLOCK	1
	$HIGH
SUBTTL	COMMON ROUTINES FOR HANDLING ERRORS IN MEMORY

;SUBROUTINE - ABSOLUTE ADDRESS TO SEGMENT NUMBER
;CALL:	MOVE	P1,ABSOLUTE ADDRESS
;	PUSHJ	P,CPIASN
;	  ERROR RETURN IF NOT IN MONITOR OR A HIGH OR LOW SEGMENT OR A UPMP
;	OK RETURN J=0 IF IN MONITOR, OR HIGH OR LOW SEG NO., OR -J IF JOB'S UPMP

CPIASN::SETZB	T2,J		;ASSUME IN MONITOR (JOB 0 NOT A LEGAL JOB #)
	LDB	T1,[POINT 13,P1,26] ;SET REL. ADR. FROM ABS. ADR IN MONITOR
	MOVE	T1,PAGTAB(T1)	;GET PAGTAB ENTRY FOR THIS PAGE
	TLNE	T1,MONTRB	;IS THIS A MONITOR PAGE?
	JRST	CPOPJ1##	;YES, GIVE OK RETURN WITH J=0
	MOVE	T3,P1		;SET T3=ABSOLUTE ADDRESS OF ERROR WORD
	LSH	T3,W2PLSH##	;T3=ABSOLUTE PAGE NUMBER OF PAGE CONTAING BAD WORD
	MOVEI	T2,JOBMAX##	;SCAN TO SEE IF BAD ADDRESS IS IN A UPMP
AUPLOP:	HRRZ	T1,JBTUPM##(T2)	;T1=PAGE NUMBER OF THE UPMP
	CAIE	T1,(T3)		;BAD WORD IN THIS UPMP?
	SOJG	T2,AUPLOP	;NO, SCAN ALL USER PAGE MAP PAGES
	JUMPG	T2,[MOVN J,T2	;IF YES, NEGATIVE JOB NUMBER TO J
		PJRST CPOPJ1##] ;SKIP RETURN
	MOVEI	J,1		;NOW SCAN ALL HIGH/LOW SEGS. STARTING WITH JOB 1
ASNLOP:	MOVEI	T1,0		;ASSUME PARITY ERROR IS IN PAGE 0 OF THIS SEGMENT
	MOVSI	T2,SHRSEG	;SHARABLE SEGMENT BIT
	CAILE	J,JOBMAX##	;IS THIS A LOW SEGMENT?
	TDNE	T2,JBTSTS##(J)	;NO--THEN IT IS A SHARABLE HIGH SEG?
	SKIPN	JBTADR##(J)	;IS THIS JOB OR HIGH SEG IN CORE?
	JRST	ASNAOJ		;NO, LOOK AT THE NEXT SEGMENT
	LDB	T2,JBYHSA##	;ASSUME ITS A HIGH SEG, GET STARTING PAGE NO.
	CAIG	J,JOBMAX##	;IS IT A HIGH SEGMENT?
	LDB	T2,JBYLSA##	;NO--GET STARTING PAGE NUMBER OF LOW SEGMENT
ASNHGH:	CAIN	T2,(T3)		;IS THIS PAGE THE SAME PAGE WHICH CONTAINED AN ERROR?
	JRST	CPOPJ1##	;YES--RETURN SEGMENT NO. IN J
	HRRZ	T2,PAGTAB(T2)	;T2=PAGE NO. OF NEXT PAGE IN THIS SEGMENT
	SKIPE	T2		;IS IT THE LAST PAGE IN THIS SEGMENT?
	AOJA	T1,ASNHGH	;NO, LOOK AT ALL THE PAGES IN THIS SEGMENT
ASNAOJ:	CAIG	J,JBTMAX##	;LOOKED AT ALL SEGMENTS?
	AOJA	J,ASNLOP	;NO, LOOK AT NEXT SEGMENT
	POPJ	P,		;NOT IN MONITOR OR ANY JOB
;SUBROUTINE TO FIX CORE ALLOCATION TABLES AFTER PAGES HAVE BEEN
; MARKED OUT IN NXMTAB DUE TO PARITY ERRORS OR NXM'S
;CALLING SEQUENCE:
;	MAKE NXMTAB REFLECT CURRENT STATE OF MEMORY, GIVE BACK CORE
;	BELONGING TO ALL SEGMENTS WHICH OVERLAP NXM, AND
;	PUSHJ	P,CPLNXF	;FIX UP RELEVANT TABLES AND VARIABLES
;RETURNS CPOPJ IF NEW VALUE OF CORMAX .LE. OLD VALUE OF CORMAX (SOME
; JOB MAY BE TOO BIG TO SWAP IN), CPOPJ1 IF ALL IS OK.
;MUST HAVE THE MM RESOURCE-CALLER'S RESPONSIBILITY

CPINXF::PUSHJ	P,SAVE2##	;SAVE WORKING ACS
	SETZB	T1,T2		;INITIALIZE INDEXS INTO PAGTAB AND NXMTAB
	MOVSI	T3,400000	;FIRST BIT TO LOOK AT IN NXMTAB
	LDB	T4,[POINT 14,MEMSIZ##,26]
	MOVSI	P1,NXMBIT	;LOOK FOR NON-EXISTANT PAGES
	HRROI	P2,MPGSIZ##	;DECREASE MAXMAX BY 1 PAGE FOR EACH NON-EXISTANT PAGE SEEN
CPINX1:	TDNN	P1,PAGTAB(T1)	;PAGE ALREADY MARKED AS NON-EXISTANT?
	TDNN	T3,NXMTAB##(T2)	;NO, IS IT NON-EXISTANT NOW?
	JRST	CPINX2		;NO, FORGE AHEAD
	SKIPL	PAGTAB(T1)	;IS THIS NON-EXISTANT PAGE ON THE FREE CORE LIST?
	STOPCD	.,STOP,NPN,	;++NON-EXISTANT PAGE NOT FREE
	ADDM	P2,MAXMAX##	;DECREASE MAXMAX BY 1 PAGE
	HLLM	P1,PAGTAB(T1)	;AND MARK THIS PAGE AS NOW NON-EXISTANT
CPINX2:	ADDI	T1,1		;NEXT PAGE
	ROT	T3,-1		;NEXT BIT POSITION IN NXMTAB
	SKIPG	T3		;CROSSED A WORD BOUNDARY?
	ADDI	T2,1		;YES, BUMP TO NEXT WORD IN NXMTAB
	SOJG	T4,CPINX1	;LOOP OVER ALL PAGES
CPINX3:	MOVE	T1,PAGPTR##	;POINTER TO THE FREE CORE LIST
	JUMPE	T1,CPINX5	;JUMP IF THERE ARE CURRENTLY NO PAGES ON THE FREE LIST
	TDNN	P1,PAGTAB(T1)	;IS THIS PAGE NOW NON-EXISTANT?
	JRST	CPINX5		;NO
	MOVE	T2,PAGTAB(T1)	;YES, LINK FREE CORE LIST AROUND THE PAGE
	HRRZM	T2,PAGPTR##	;STORE NEW FIRST PAGE ON THE FREE CORE LIST
	SOS	CORTAL##	;DECREMENT COUNT OF POTENTIALLY FREE PAGES
	SOS	BIGHOL##	;DECREMENT COUNT OF FREE PAGES
	JRST	CPINX3		;CONTINUE TO LOOK AT PAGES AT THE BEGINNING
				; OF THE FREE CORE LIST
CPINX4:	MOVE	T1,T2		;CURRENT INDEX INTO PAGTAB
CPINX5:	HRRZ	T2,PAGTAB(T1)	;NEXT PAGE IN PAGTAB
	JUMPE	T2,CPINX6	;JUMP IF THIS IS THE END OF THE FREE CORE LIST
	TDNN	P1,PAGTAB(T2)	;IS THIS PAGE NOW NON-EXISTANT?
	JRST	CPINX4		;NO
	HRRZ	T2,PAGTAB(T2)	;YES, LINK THE FREE CORE LIST AROUND IT
	HRRM	T2,PAGTAB(T1)	; ..
	SOS	CORTAL##	;DECREMENT THE COUNT OF POTENTIALLY FREE PAGES
	SOS	BIGHOL##	;AND THE COUNT OF FREE PAGES
	JRST	CPINX5		;LOOP OVER THE ENTIRE FREE CORE LIST
CPINX6:	MOVEI	T1,0		;INITIALIZE COUNT OF EXISTANT UNLOCKED PAGES
	MOVE	T2,MEMSIZ##	;PREVIOUS HIGHEST ADDRESS + 1
	SUB	T2,SYSSIZ##	;RANGE OF USERS CORE
	LSH	T2,W2PLSH##	;NUMBER OF PAGES FROM TOP OF THE MONITOR
				; TO THE PREVIOUS TOP OF MEMORY
	MOVE	T3,SYSSIZ##	;WHERE TO START LOOKING FOR UNLOCKED EXISTANT PAGES
	LSH	T3,W2PLSH##	;PAGE NUMBER TO START AT
CPINX7:	MOVE	P1,PAGTAB(T3)	;PAGE DESCRIPTOR BITS FROM PAGTAB
	TLNE	P1,LKBITS-MONTRB;IS THIS PAGE LOCKED OR NON-EXISTANT?
	JRST	CPINX8		;YES, DON'T CONSIDER IT IN COMPUTING NEW CORMAX
	MOVEI	T4,1(T3)	;HIGHEST EXISTANT PAGE + 1 THAT WAS SEEN
	TLNN	P1,MONTRB	;IS THIS A MONITOR PAGE?
	ADDI	T1,PAGSIZ##	;NO, INCREASE NEW CORMAX BY ONE PAGE
CPINX8:	ADDI	T3,1		;NEXT PAGE IN PAGTAB
	SOJG	T2,CPINX7	;LOOP OVER ALL PAGES
	MOVEI	T2,PAGTAB-1(T4)	;BYTE POINTER TO HIGHEST PAGE
	HRRM	T2,CORLST##	;STORE THAT FOR CHKTAL
	LSH	T4,P2WLSH##	;HIGHEST EXISTANT ADDRESS + 1
	MOVEM	T4,MEMSIZ##	;STORE THAT AS THE SIZE OF MEMORY
	MOVE	T2,MAXMAX##	;MAXIMUM CORMAX
	SUBI	T2,NWMCP	;FUNNY SPACE
	CAMLE	T1,T2		;ROOM FOR FUNNY PAGES?
	MOVE	T1,T2		;NO, MAKE ROOM
	CAML	T1,CORMAX##	;NEW CORMAX LESS THAN THE OLD CORMAX?
	AOSA	(P)		;NO, INDICATE ALL JOBS CAN STILL RUN
	MOVEM	T1,CORMAX##	;YES, STORE NEW VALUE OF CORMAX AND GIVE
				; A NON-SKIP RETURN TO INDICATE THAT SOME
				; JOBS MAY BE TOO LARGE TO BE SWAPPED IN
	POPJ	P,		;RETURN
SUBTTL	ERROR REPORTING FOR CHANNEL ERRORS
IFN FTKI10!FTKL10,<
;SUBROUTINE TO STORE CHANNEL DATA ON ALL HARD AND SOFT ERRORS
;CALL:	MOVE	F,DEVICE DATA BLOCK ADR
;	MOVE	U,UNIT DATA BLOCK ADR
;	MOVE	P1,CHANNEL DATA BLOCK ADDRESS(CHN'N'CB)
;	MOVE	T1,ADDRESS OF FIRST CCW IN CCW LIST
;	PUSHJ	P,CHNMPE OR CHNNXM (MEMORY PARITY OR NXM)
;	RETURN WILL ALL REGISTERS PRESERVED EXCEPT T1-T4

;SUBROUTINE FOR MEMORY PARITY
CHNMPE::AOS	.CHMPE(P1)	;INCREMENT NO. OF MEM PARITY ERRORS
	PUSHJ	P,SAVE4##	;SAVE P REGISTERS
	SETO	P4,		;INDICATE PARITY ERROR
	JRST	CHNCOM		;JOIN COMMON CODE

;SUBROUTINE FOR NXM
CHNNXM::AOS	.CHNXM(P1)	;INCREMENT NO. OF NXMS
	PUSHJ	P,SAVE4##	;SAVE P REGISTERS
	SETZ	P4,		;INDICATE NXM ERROR
CHNCOM:	SETOM	.CPCHE##	;FLAG CHANNEL ERROR CODE IS RUNNING
	HRRM	U,.CHLUE(P1)	;SAVE UNIT DATA BLOCK ADR
	HRRM	F,.CHLDE(P1)	;SAVE DEVICE DATA BLOCK ADR
	PUSH	P,U		;SAVE U
	HRRZ	U,.CPCTN	;GET CPU'S CTY LINE NUMBER
	HRRZ	U,LINTAB##(U)	;GET CTY'S LDB
	PUSHJ	P,CHNCCW	;COLLECT CCW DATA
	SKIPE	P4		;IS THIS A NXM ERROR?
	PUSHJ	P,CHNDAT	;NO--COLLECT DATA WORDS ALSO
	MOVEI	T1,SDELIM	;GET ADRESS OF TEXT
	PUSHJ	P,CONMES##	;PRINT START DELIMITER
	MOVE	T2,.CPLOG##	;GET THIS CPU'S NAME
	PUSHJ	P,PRNAME	;PRINT IT
	SKIPE	P4		;NXM ERROR?
	SKIPA	T1,[[ASCIZ / channel memory parity error on /]] ;NO--PARITY ERROR
	MOVEI	T1,[ASCIZ / channel non-existent memory error on /] ; YES--NXM
	PUSHJ	P,CONMES##	;PRINT ERROR TYPE
	PUSHJ	P,DAYTIM##	;APPEND DATE AND TIME
	MOVEI	T1,[ASCIZ /Device in use is /] ;GET TEXT
	PUSHJ	P,CONMES##	;PRINT DEVICE PREFIX MESSAGE
	MOVE	T2,DEVMOD(F)	;GET DEVICES CHARACTERISTICS
	HRR	T2,.CHLUE(P1)	;UDB OF DEVICE WHERE ERROR HAPPENED
	TLNE	T2,DVDSK	;IS THIS A DISK?
	SKIPA	T2,(T2)		;YES--GET NAME FROM UDB
	MOVE	T2,DEVNAM(F)	;NO--GET DEVICE NAME FROM DDB
	PUSHJ	P,PRNAME	;APPEND IT
	MOVEI	T1,[ASCIZ /
Channel type is /] ;GET TEXT
	PUSHJ	P,CONMES##	;PRINT CHANNEL TYPE PREFIX MESSAGE
	MOVE	T2,CHB22B##(P1)	;GET CHANNEL TYPE BITS
	TLNN	T2,CP.22B	;22-BIT CHANNEL?
	SKIPA	T1,[[ASCIZ /DF10/]] ;NO--DEFINITELY A DF10
	MOVEI	T1,[ASCIZ /DF10-C/] ;YES--POSSIBLY A DF10-C
	TLNE	T2,CP.DX1	;IS IT A DX10?
	MOVEI	T1,[ASCIZ /DX10/] ;YES--GET ITS TEXT
	TLNE	T2,CP.RH2	;IS IT AN RH20?
	MOVEI	T1,[ASCIZ /RH20/] ;YES--GET ITS TEXT
	PUSHJ	P,CONMES##	;APPEND CHANNEL TYPE
	MOVEI	T1,[ASCIZ /
Termination channel program address = /] ;GET TEXT
	PUSHJ	P,CONMES##	;PRINT TERM. CCW ADDRESS MESSAGE
	HLRZ	T1,.CHFCW(P1)	;GET LH TERMINATION CCW
	SKIPGE	CHB22B##(P1)	;IS THIS A 22-BIT CHANNEL?
	LSH	T1,-4		;YES--THEN ONLY 14 BITS ARE CCW ADDRESS
	PUSHJ	P,OCTPNT	;PRINT IT
	MOVEI	T1,[ASCIZ /
Termination data transfer address = /] ;GET TEXT
	PUSHJ	P,CONMES##	;PRINT TERM. DATA ADDRESS MESSAGE
	MOVE	T1,.CHFCW(P1)	;GET RH TERMINATION CCW
	SKIPGE	CHB22B##(P1)	;IS THIS A 22-BIT CHANNEL?
	TLZA	T1,777760	;YES--GET JUST DATA ADDRESS (22 BITS)
	TLZ	T1,-1		;NO--GET JUST DATA ADDRESS (18 BITS)
	PUSHJ	P,PRT22A	;PRINT IT
	MOVEI	T1,[ASCIZ /
Last three channel commands executed are:
/]
	PUSHJ	P,CONMES##	;PRINT THIS
	MOVE	T1,.CHCW0(P1)	;ARE ALL CCW'S ZERO?
	IOR	T1,.CHCW1(P1)	;...
	IOR	T1,.CHCW2(P1)	;...
	SKIPE	T1		;...
	JRST	CHNCO1		;NO--GO PRINT THEM OUT
	PUSHJ	P,PR3SPC##	;YES--INDENT
	MOVEI	T1,[ASCIZ /** Indeterminate **
/]
	PUSHJ	P,CONMES##	;TELL THEM WE DON'T KNOW
	JRST	CHNCO3		;CONTINUE
CHNCO1:	MOVSI	P2,-3		;FORM AOBJN POINTER
	HRRI	P2,.CHCW2(P1)	; TO SAVED CCW'S
CHNCO2:	PUSHJ	P,PR3SPC##	;INDENT
	MOVE	T1,(P2)		;PICK UP CCW
	PUSHJ	P,HWDPNT	;PRINT IT
	PUSHJ	P,CRLF##	;PRINT CRLF
	AOBJN	P2,CHNCO2	;LOOP IF MORE
CHNCO3:	MOVEI	T1,EDELIM	;GET ENDING DELIMITER
	PUSHJ	P,CONMES##	;PRINT IT
	POP	P,U		;RESTORE U
	SETZM	.CPCHE##	;CLEAR CHANNEL ERROR IN PROGRESS FLAG
	MOVEI	T1,.ERCPE	;CHANNEL ERROR CODE
	HRL	T1,P1		;GET CDB ADDRESS
	PUSH	P,J		;SAVE J
	PUSHJ	P,DAEEIM##	;POKE DAEMON
	POP	P,J		;RESTORE J
	POPJ	P,		;RETURN
;ROUTINE TO STORE CCW DATA FOR CHANNEL ERRORS
CHNCCW:	MOVE	T3,CHB22B##(P1)	;PICK UP CHANNEL TYPE BITS
	MOVE	T2,0(T1)	;GET FIRST CCW IN LIST
	MOVEM	T2,.CHICW(P1)	;SAVE IN CDB FOR F.S.
	TLNN	T3,CP.RH2##	;IS THIS AN RH20?
	JRST	CHNCC1		;NO--PROCEED
	HRRZ	T2,1(T1)	;YES--GET LAST CCW ADDR + 1
	MOVE	P3,2(T1)	;GET TERMINATION CCW
	MOVEM	P3,.CHFCW(P1)	;SAVE IN CDB FOR F.S.
	JRST	CHNCC4		;CONTINUE
CHNCC1:	TLNN	T3,CP.DX1##	;IS THIS A DX10?
	JRST	CHNCC2		;NO--PROCEED
	DPB	P2,[POINT 14,P3,13] ;YES--COMBINE IN TERM. CHANNEL PROGRAM COUNTER
	JRST	CHNCC3		;CONTINUE
CHNCC2:	MOVE	P3,1(T1)	;GET TERMINATION CCW FOR DF10/DF10-C
CHNCC3:	MOVEM	P3,.CHFCW(P1)	;SAVE IN CDB FOR F.S.
	HLRZ	T2,P3		;GET ADDRESS OF LAST CCW
	TLNE	T3,CP.22B##	;IS THIS A 22-BIT CHANNEL?
	LSH	T2,-4		;YES--THEN ONLY 14 BITS ARE CCW ADDRESS
CHNCC4:	TLNE	T3,CP.RH2##	;IS THIS AN RH20?
	SOS	T2		;BACK UP LAST CCW ADDRESS BY 1
	MOVE	P2,T2		;SAVE REAL FINAL CCW ADDRESS HERE
	CAIL	T2,2		;IS FIRST SOURCE ABOVE LOC 0?
	CAML	T2,MEMSIZ##	;YES, IS LAST SOURCE ADR IN BOUNDS?
	JRST	CHNCC6		;NO--JUNK DATA, DON'T ATTEMPT RETRIEVAL
CHNCC5:	MOVE	P3,.CHCW0(P1)	;PUSH EVERYBODY DOWN ONE
	EXCH	P3,.CHCW1(P1)	;...
	MOVEM	P3,.CHCW2(P1)	;...
	MOVE	P3,(T1)		;GET THIS CCW
	MOVEM	P3,.CHCW0(P1)	; AND SAVE AS LAST CCW
	CAMN	P2,T1		;DOES ITS ADDRESS MATCH THE CHANNEL TERM ADDR?
	JRST	CHNCC7		;YES--WE'RE DONE, STOP CHASING LIST
	TLNE	P3,577777	;IS CCW A DATA TRANSFER?
	AOJA	T1,CHNCC5	;YES--BUMP CCW ADDRESS AND GO AROUND AGAIN
	JUMPE	P3,CHNCC6	;NO--IF IT'S A HALT, WE'VE RUN OUT UNEXPECTEDLY
	TLNE	T3,CP.DX1##	;IS THIS A DX10?
	TLNE	P3,200000	;YES--IS THIS A DX10 DEVICE COMMAND CCW?
	SKIPA			;NO--NOT DX10 OR IT'S A DX10 JUMP
	AOJA	T1,CHNCC5	;YES--BUMP CCW ADDRESS AND GO AROUND AGAIN
	MOVE	T1,(T1)		;IT'S A JUMP, GET NEXT CCW ADDRESS
	TLNE	T3,CP.22B##	;IS THIS A 22-BIT CHANNEL?
	TLZA	T1,777760	;YES--GET JUST ADDRESS (22-BITS)
	TLZ	T1,-1		;NO--GET JUST ADDRESS (18-BITS)
	JRST	CHNCC5		; AND GO AROUND AGAIN
CHNCC6:	SETZM	.CHCW2(P1)	;ZERO THE CCW LOCATIONS
	SETZM	.CHCW1(P1)	;...
	SETZM	.CHCW0(P1)	;...
CHNCC7:	MOVE	T2,CHNTCW##(P1)	;GET EXPECTED TERMINATION CCW
	MOVEM	T2,.CHTCW(P1)	;SAVE FOR F.S.
	POPJ	P,		;RETURN
;HERE TO COLLECT RELEVANT DATA WORDS ON PARITY ERROR
CHNDAT:	MOVE	T4,.CHFCW(P1)	;GET TERMINATION CCW
	SKIPGE	CHB22B##(P1)	;IS THIS A 22-BIT CHANNEL?
	TLZA	T4,777760	;YES--GET JUST ADDRESS (22-BITS)
	TLZ	T4,-1		;NO--GET JUST ADDRESS (18-BITS)
	CAIL	T4,2		;IS LAST DATA ADR ABOVE 0?
	CAML	T4,MEMSIZ##	;YES, IS IT IN BOUNDS?
	JRST	CHNDA2		;NO--JUNK DATA, DON'T ATTEMPT RETRIEVAL
	PUSHJ	P,MAPLOC##	;GET EVA SLOT
	MOVEI	T3,.ERPIL(T3)	;FORM EVA PAGE NUMBER
	SUBI	T4,2		;BACK UP STARTING ADDRESS BY TWO
	MOVEI	P2,.CHDW2(P1)	;PLACE TO STORE DATA WORDS
	HRLI	P2,-3		;MAKE AOBJN PNTR
CHNDA1:	LDB	P3,[POINT 13,T4,26] ;GET PAGE NUMBER
	IORI	P3,PM.ACC!PM.WRT ;SET ACCESS BITS
	DPB	P3,T1		;MAP THIS PAGE
	CLRPGT	(0)		;CLEAR PAGING MEMORY
	DPB	T4,[POINT 9,T3,35] ;SET LINE # IN PAGE
	MOVE	P3,(T3)		;FETCH DATA WORD
	MOVEM	P3,(P2)		;STASH IN CDB
	ADDI	T4,1		;ADVANCE TO NEXT LOC
	AOBJN	P2,CHNDA1	;LOOP TILL DONE
	MOVEI	T2,↑D50		;WAIT FOR ANY PARITY INTERRUPTS
	SOJG	T2,.		;TO HAPPEN (IF ANY)
	POPJ	P,		;RETURN
CHNDA2:	SETZM	.CHDW0(P1)	;ZERO THE DATA LOCATIONS
	SETZM	.CHDW1(P1)	;...
	SETZM	.CHDW2(P1)	;...
	POPJ	P,		;RETURN
>;END IFN FTKI10!FTKL10

IFN FTKS10,<
CHNMPE::
CHNNXM::POPJ	P,
>;END IFN FTKS10
SUBTTL	STOPCODE PROCESSING
;ROUTINE TO RECOVER/RELOAD AFTER AN INTERNAL
; SYSTEM ERROR.  CALLED ONLY BY STOPCD MACRO
; (SEE S.MAC) WITH:
;	PUSHJ	P,DIE
;	CAI	TYPE,NAME (CONT)
;
;	-OR-
;
;	PUSHJ	P,DIE
;	CAIA	TYPE,NAME (17)
;	JRST	CONT
;
DIE::	AOSE	.CPDWD##	;INTERLOCK STOPCD CODE
	STOPCD	.,HALT,REH,	;++RECURSION IN ERROR HANDLER
	CONI	PI,.CPCPI##	;SAVE STATE OF MACHINE
	CONO	PI,PI.TFP+177	; ..
	JSR	.CPSVA##	;SAVE ALL AC SETS
	MOVE	T1,.UPMP+.UPMUO
	MOVEM	T1,.CPTRP##
	MOVE	M,@(P)		;M=FLAG WORD
	POP	P,T1		;GET PC OF STOPCD
	MOVEM	T1,%SYSPC##	;STORE IN TRADITIONAL WORD
	MOVEM	T1,.CPSUP##	; AND IN CDB
	MOVE	P,.CPEPD##	;SETUP PDL FOR THIS CPU
	PUSHJ	P,RCDSTB##	;READ CPU AND DEVICE STATUS BLOCKS
IFN FTKL10,<
	PUSHJ	P,CSDMP##	;MAKE SURE IT'S ALL IN CORE
	PUSHJ	P,SKPMRN##	;SKIP IF MASTER -11 IS RUNNING
	STOPCD	.,HALT,MNR,	;++MASTER -11 NOT RUNNING
	PUSHJ	P,DIE1		;PROCESS STORAGE
	JRST	RESRET		;RESTORE & RETURN
DIE1:	PUSHJ	P,SVPPC##	;SAVE PROTOCOL
>
IFN FTKS10,<
	PUSHJ	P,DISKAL##	;DISABLE KEEP ALIVE FUNCTION
>
IFN FTMP,<
DIE2:	AOSN	DIELOK##	;GET DIE INTERLOCK
	JRST	DIE3		;GOT IT, CONTINUE
	SKIPN	CRSHWD##	;RELOADING?
	JRST	DIE2		;NO, LOOP FOR INTERLOCK
	PJRST	REBOOT##	;YES
DIE3:
IFN FTKI10,<
	CONI	PAG,INODIE##	;MAKE ME THE OWNER OF THE INTERLOCK
>
IFN FTKL10,<
	APRID	INODIE##	;MAKE ME THE OWNER OF THE INTERLOCK
>
>
	PUSH	P,.CPTOA##	;SAVE ADDRESS OF TYPEOUT ROUTINE
	MOVEI	T1,CTYWAT##	;REPLACE IT WITH ONE THAT DOESN'T USE PI'S
	MOVEM	T1,.CPTOA##	;MODIFY SCNSER
	HRRZ	U,.CPCTN##	;POINT TO CONSOLE TERMINAL FOR THIS CPU
	MOVEI	T2,↑D10		;SEND 10 BELLS
	PUSHJ	P,BELLS		;..
	PUSHJ	P,INLMES##	;PRINT MESSAGE
	ASCIZ	/
?/
	MOVE	T2,.CPLOG##
	PUSHJ	P,PRNAME
	PUSHJ	P,INLMES##
	ASCIZ	/ monitor error. Stopcode name is /
	HRLZ	T2,M		;GET CODE
	TLNE	M,(Z 10,0)	;LONG FORM
	HRLZ	T2,0(M)		;YES, GET CODE
	HLLM	T2,%SYSPC##	;SAVE NAME
	HLLM	T2,.CPSNM##
	PUSHJ	P,PRNAME	;PRINT IT OUT
	PUSHJ	P,CRLF##	;ADD A CRLF
	MOVE	J,.CPJOB##
	MOVEI	S,PI.IPA	;GET PI ON MASK
	AND	S,.CPCPI##	;MASK OUT ALL ELSE
	SKIPN	S		;INTERRUPT LEVEL?
	PUSHJ	P,WHATJB	;NO--GIVE INFO
	TLZ	F,-1		;CLEAR LH BITS
	PUSHJ	P,CHKDDB	;MAKE SURE THAT F POINTS TO A DDB
	  JRST	NODDB		;IT DOESN'T, DON'T PRINT THE INFORMATION
	LDB	T1,PJOBN##	;GET JOB #
	CAILE	T1,JOBMAX##	;TOO BIG?
	JRST	NODDB		;YES--NOT A DDB
	JUMPE	T1,NODDB	;WANT REAL JOB #
	PUSHJ	P,INLMES##
	ASCIZ	/File /
	PUSHJ	P,PRTDDB##	;PRINT DDB STUFF
	PUSHJ	P,CRLF##	;ADD CRLF
	JUMPE	S,NODDB		;UUO LEVEL-SAID THIS
	LDB	J,PJOBN##	;GET JOB #
	PUSHJ	P,WHATJB	;PRINT IT
NODDB:	TLZN	M,(Z 10,0)	;ADDITIONAL INFORMATION
	JRST	NOTYPE		;NO, PRESS ON
	HLRZ	T1,0(M)		;TYPE OUT ROUTINE
	HRR	M,0(M)		;PUT STOPCD NAME INTO RH OF M
	JUMPE	T1,NOTYPE	;REALLY SHOULD BE ONE
	PUSHJ	P,0(T1)		;CALL IT
	PUSHJ	P,CRLF##	;TERMINATE LINE
NOTYPE:	SKIPGE	DEBUGF## 	;WANT DDT?
	JRST	DIEADP		;YES
	PUSHJ	P,TYPCSB##	;TYPE CPU STATUS BLOCK INFO ON THE CTY
	LDB	T1,PUUOAC##	;GET ERROR TYPE
	CAIL	T1,1		;BE SURE IT'S IN RANGE
	CAILE	T1,4		;JUST SUPER CAUTIOUS
	JRST	RELOAD		;BAD. DON'T MAKE IT WORSE
	JRST	@[EXP RELOAD,ZAPJOB,BUGCHK,CPUSTP]-1(T1)
;HERE ON A DEBUG STOPCD

BUGCHK:	PUSHJ	P,STCLIM	;EXCEED STOPCD LIMIT?
	  JRST	SCLEXC		;YES
	MOVSI	T1,(DF.RDC)	;DO WE WANT TO
	TDNE	T1,DEBUGF##	; RELOAD?
	JRST	RELOAD		;YES--GO RELOAD
	AOS	%SYNDS##	;COUNT BUG
	AOS	.CPSND##
IFN FTMBTS,<
	MOVSI	T1,(DF.DDC)	;WANT TO DUMP ON
	TDNN	T1,DEBUGF##	;  THIS TYPE OF STOPCD?
	PUSHJ	P,CRSDMP	;DUMP SYSTEM AND RETURN
>
	PUSHJ	P,INLMES##	;NO--CONTINUE
	ASCIZ	/[Continuing system]
/
DIEADP:	MOVE	T3,.CPACA##	;GET ADDRESS OF SAVED AC BLOCK
	MOVE	T1,P(T3)	;GET OLD STACK POINTER
	LDB	T2,[POINT 4,M,17]	;GET RETURN TYPE
	XCT	CONTAB(T2)	;FIX UP PDP
	MOVEM	T1,P(T3)	;SAVE BACK
	JRST	DIERS0		;RESTORE STATE OF MACHINE


;HERE ON A JOB ERROR STOPCD

ZAPJOB:	PUSHJ	P,STCLIM	;STOPCD LIMIT EXCEEDED?
	  JRST	SCLEXC		;YES
	MOVSI	T1,(DF.RJE)	;IS RELOAD ON JOB ERROR
	TDNN	T1,DEBUGF##	; REQUESTED?
	SKIPE	S		; OR PI LEVEL?
	JRST	RELOAD		;YES--GO RELOAD
	SKIPE	.UPMP+.UPJOB	; CAN'T STOP THE NULL JOB.
	SKIPE	.CPISF##	;IN SCHEDULER CONTEXT?
	JRST	RELOAD		;YES, CAN'T REALLY STOP A JOB
	AOS	%SYNJS##	;COUNT BUG
	AOS	.CPSNJ##
IFN FTMBTS,<
	MOVSI	T1,(DF.DJE)	;WANT TO DUMP ON
	TDNN	T1,DEBUGF##	;  THIS TYPE OF STOPCD?
	PUSHJ	P,CRSDMP	;DUMP SYSTEM AND RETURN
>
	PUSHJ	P,INLMES##	;NO--ZAP JOB
	ASCIZ	/[Aborting job]
/
	PUSHJ	P,GIVLOK##	;GIVE BACK LOCKS THIS CPU OWNS
	MOVE	T2,.CPACA##	;GET ADDRESS OF AC BLOCK
	MOVEI	T1,BUGSTP	;ADJUST SAVED STACK
	MOVE	T2,P(T2)	;SO THIS JOB GETS
	MOVEM	T1,(T2)		;KILLED
	JRST	DIERS0		;RESTORE STATE OF SYSTEM
;HERE ON A CPU STOPCD

IFN FTMP,<
CPUSTP:	PUSHJ	P,STCLIM	;STOPCD LIMIT EXCEEDED?
	  JRST	SCLEXC		;YES
	MOVSI	T2,(DF.CP1)	;BIT FORCING CPU STOPCDS TO CAUSE RELOAD
	PUSHJ	P,LSTCPU##	;LAST OR ONLY CPU RUNNING IN SYSTEM?
	TDNE	T2,DEBUGF##	;NO, WANT TO RELOAD ON CPU STOPCDS?
	JRST	RELOAD		;YES, RELOAD THE SYSTEM
	AOS	.CPSNC##	;COUNT BUG
IFN FTMBTS,<
	MOVSI	T1,(DF.DCP)	;WANT TO DUMP ON
	TDNN	T1,DEBUGF##	;  THIS TYPE OF STOPCD?
	PUSHJ	P,CRSDMP	;DUMP SYSTEM AND RETURN
>
	PUSHJ	P,INLMES##	;TELL OF OUR ACTION
	ASCIZ	/[Stopping CPU]
/
	PUSHJ	P,KILUSR	;INSURE THAT THE CURRENT JOB IS STOPPED
				;  TO AVOID A REPEAT OF THE STOPCD IF
				;  HE STARTS TO RUN ON ANOTHER CPU
	POP	P,.CPTOA##	;RESTORE SCNSER TYPOUT ADDRESS
	SETOM	.CPOK##		;INSURE THAT BECOM0 WILL BE CALLED
	SETOM	INODIE##	;NO LONGER INTERLOCK OWNER
	SETOM	DIELOK##	;NO LONGER HAVE INTERLOCK
	MOVEI	T1,SR.DIE	;TELL CP1CRS THAT WE WANT THE OPERATOR
	IORM	T1,.CPSBR##	;  TO MANUALLY RESTART THIS CPU
	SKPCPU	(1)		;IF ON THE BOOT CPU, WAIT FOR SOMEONE
	JRST	.-1		;  TO ASSUME THE ROLE
	PJRST	REBOOT##	;SAVE STATE OF THE MACHINE
>
;HERE IF WE EXCEEDED ONE OF THE STOPCD-PER-UNIT-TIME LIMITS TO RELOAD
;THE SYSTEM.

SCLEXC:	PUSHJ	P,INLMES##	;TELL WHAT HAPPENED
	ASCIZ/?Stopcode limit exceeded
/


;HERE TO RELOAD THE SYSTEM

IFE FTMP,<
CPUSTP:
>
RELOAD:	HRRZM	M,CRSWHY##	;SAVE REASON FOR ONCE ATER RELOAD
	PUSHJ	P,INLMES##
	ASCIZ	/Reload monitor
/
	MOVEI	T2,↑D20		;20 BELLS
	PUSHJ	P,BELLS		;..
	MOVE	P,.CPACA##	;GET ADDRESS OF AC BLOCK
	MOVE	P,P(P)		;RESTORE PDP
	POP	P,CRSHWD##	;SAVE PC
	SOS	CRSHWD##	;FOR SYSTAT/X
	PJRST	REBOOT##	;YES, RELOAD NOW


;HERE TO RESTORE THE STATE OF THE MACHINE

DIERS0:	POP	P,.CPTOA##	;RESTORE SCNSER
IFN FTKL10,<
	POPJ	P,		;RETURN ON A KL
>

RESRET:
IFN FTDAEM,<
	PUSHJ	P,DAEEST##	;TELL DAEMON OF STOPCD
>
	MOVEI	T1,177		;ALL PI BITS
	AND	T1,.CPCPI##	;TURN ON ONLY
	IORI	T1,PI.TNP	;ONES WHICH WERE ON
	MOVEM	T1,.CPCPI##	;SAVE FOR CONO
	HRLZ	17,.CPACA##	;WHERE TO RESTORE THE AC'S FROM
	BLT	17,17		;RESTORE THEM ALL
IFN FTMP,<
	SETOM	INODIE##	;NO LONGER THE OWNER OF THE INTERLOCK
	SETOM	DIELOK##	;OR HAVE THE INTERLOCK
>
	CONO	PI,@.CPCPI##	;TURN ON PI SYSTEM
	SKIPGE	DEBUGF##	;WANT DDT?
	XCT	SYSDDT##	;YES
DIECON::SETOM	.CPDWD##	;ALLOW STOPCD'S
IFN FTKS10,<
	PUSHJ	P,ENAKAL##	;ENABLE KEEP ALIVE FUNCTION
>
	POPJ	P,
;HERE TO STOP AN ILL FATED USER
BUGSTP:	MOVE	J,.CPJOB##	;JOB NUMBER
	PUSHJ	P,ZAPUSR	;GIVE UP LOCKS AND DEVICES
	JSP	T1,ERRPTU	;PRINT MESSAGE
	ASCIZ	/Monitor error/
	PJRST	UUOPCP		;PRINT SOME PC'S


;ROUTINE TO KILL THE CURRENT JOB RUNNING ON THIS CPU TO MAKE SURE
;THAT IT DOESN'T CONTINUE TO CAUSE THE SAME CRASH OVER AND OVER AGAIN.
;MUST NOT BE CALLED WITH A UUO LEVEL STACK SINCE ZAPPGM WILL GIVE
;BACK THE PAGE MAP.

KILUSR:	PUSHJ	P,GIVLOK##	;RETURN INTERLOCKS OWNED BY THIS CPU
	SKIPN	J,.CPJOB##	;ANY JOB RUNNING ON THIS CPU?
	POPJ	P,		;NO, JUST RETURN
	PUSHJ	P,ZAPUSR	;GIVE UP LOCKS AND DEVICES
	PUSH	P,JBTSTS##(J)	;SAVE CURRENT STATE OF JBTSTS
	MOVSI	T1,JLOG		;CLEAR JLOG TEMPORARILY SO THAT
	ANDCAM	T1,JBTSTS##(J)	;  ZAPPGM WILL GIVE BACK ALL OF THE
	ANDM	T1,0(P)		;  USER'S CORE.  I KNOW IT'S UGLY BUT...
	PUSHJ	P,ZAPPGM##	;GIVE BACK ALL OF HIS CORE
	POP	P,T1		;GET BACK STATE OF JLOG BIT
	IORM	T1,JBTSTS##(J)	;SET IT IF IT WAS SET BEFORE
	POPJ	P,		;RETURN
;SUBROUTINE TO SEND C(T2) BELLS
;CLOBBERS T1, T2, T3, T4
BELLS::	MOVEI	T3,"G"-100	;BELL
BELOOP:	PUSHJ	P,COMTYO##	;DING
	MOVEI	T1,200000
	LSH	T1,-2*FTKL10-FTKI10
	SOJG	T1,.
	SOJG	T2,BELOOP	;LOOP FOR ALL
	POPJ	P,		;RETURN


;ROUTINE TO CHECK A DDB ADDRESS BEFORE USING IT TO TYPE FILE INFORMATION
;DURING DIE PROCESSING.
;CALL:	MOVEI	F,ADDRESS
;	PUSHJ	P,CHKDDB
;	  RETURN HERE IF ADDRESS IS ILLEGAL FOR SOME REASON
;	RETURN HERE IF ADDRESS IS OK

CHKDDB:	CAMGE	F,SYSSIZ##	;LARGER THAN THE LOW SEG?
	CAIG	F,1000		;OR TOO SMALL?
	CAIA			;YES, MAY STILL BE IN FUNNY SPACE
	JRST	CPOPJ1##	;GIVE SKIP RETURN
	CAIL	F,.FPMC		;LEGAL ADDRESS IN
	CAIL	F,.FPMC+NWMCP	;  FUNNY SPACE?
	POPJ	P,		;NO, BAD DDB ADDRESS
	MAP	T1,(F)		;MAP THE ADDRESS
	PUSHJ	P,FLTCHK##	;WILL REFERENCE FAULT?
	  POPJ	P,		;YES, BAD ADDRESS
	MAP	T1,DEVSFD##(F)	;LAST ADDRESS IN DDB REFERENCED BY PRTDDB
	PJRST	FLTCHK##	;CHECK ADDRESS AND RETURN
;ROUTINE TO SEE IF THIS STOPCD HAS CAUSED US TO EXCEED ON OF THE
;STOPCDS-PER-UNIT-TIME LIMITS.
;CALL:	PUSHJ	P,STCLIM
;	  RETURN HERE IF A LIMIT HAS BEEN EXCEEDED
;	  RETURN HERE IF NOT

STCLIM:	SKIPGE	DEBUGF##	;IF DEBUGGING
	JRST	CPOPJ1##	;THEN NOSTOPCD LIMITS
	MOVSI	T1,-SCCTBL##	;BUILD AOBJN POINTER TO TABLE
STCLI1:	AOS	T2,SCCTAB##(T1)	;INCREMENT NEXT COUNT
	HRRZ	T3,SCLTAB##(T1)	;GET THE LIMIT
	CAIL	T2,(T3)		;EXCEED THE LIMIT?
	POPJ	P,		;YES
	AOBJN	T1,STCLI1	;NO, LOOP FOR NEXT
	HLRZ	T1,SCLTAB##+0	;GET PERIOD OF LOWEST ENTRY IN TABLE
	IMUL	T1,TICSEC##	;SETUP CLOCK REQUEST TO DECREMENT THE
	HRLI	T1,DECSCC	;  1 MINUTE STOPCD COUNT. DECSCC WILL,
	MOVEI	T2,0		;  IN TURN, PUT IN A CLOCK REQUEST TO DECREMENT
	IDPB	T1,CLOCK##	;  THE NEXT ONE, AND SO ON, UNTIL ALL
	IDPB	T2,CLOCK##	;  LEVELS OF COUNTS HAVE BEEN DECREMENTED.
	SETOM	CLKNEW##	;I REALIZE THE CLOCK QUEUE HASN'T BEEN
				;  INTERLOCKED WITH SYSPIF BUT BY THE
				;  TIME THE FIRST CHARACTER OF THE STOPCD
				;  MESSAGE HAS TYPED ON THE CTY, ALL OTHER
				;  CPU'S SHOULD HAVE SEEN DIELOK GO NON-ZERO
	JRST	CPOPJ1##	;GIVE SKIP RETURN


;ROUTINE TO DECREMENT A STOPCD COUNT AND RESUBMIT A CLOCK QUEUE REQUEST
;FOR THE NEXT HIGHER COUNT, IF ONE EXISTS.
;CALL:	MOVEI	T1,INDEX INTO SCCTAB
;	PUSHJ	P,DECSCC
;	  RETURN HERE ALWAYS


DECSCC::SOSGE	SCCTAB##(T1)	;DECREMENT COUNT
	SETZM	SCCTAB##(T1)	;LEAVE ZERO IF IT WAS ZERO
	AOS	T1		;INCREMENT LEVEL
	CAIL	T1,SCCTBL##	;DONE THE LAST LEVEL?
	POPJ	P,		;YES, RETURN NOW
	MOVE	T2,SCLTAB##(T1)	;GET WORD WITH NEW PERIOD
	SUB	T2,SCLTAB##-1(T1) ;SUBTRACT OLD PERIOD
	HLRZS	T2		;KEEP JUST DIFFERENCE IN PERIODS
	IMUL	T2,TICSEC##	;CONVERT TO TICKS
	HRLI	T2,DECSCC	;WANT TO COME BACK HERE
	SYSPIF			;INTERLOCK THE QUEUE
	IDPB	T2,CLOCK##	;STORE REQUEST
	IDPB	T1,CLOCK##	;  AND DATA
	SETOM	CLKNEW##	;FLAG A NEW REQUEST
	PJRST	ONPOPJ##	;RETURN INTERLOCK AND POPJ
;ROUTINES FOR STOPCODE MACRO TYPE OUT
;ALL ROUTINES WILL HAVE THE FORM DIE???::
;WHERE ??? ARE 3 LETTERS DESCRIPTIVE OF THE ROUTINE
;AN AUTOMATIC CARRIAGE RETURN/LINE FEED IS DONE BY CALLER

;ROUTINE TO TYPE OUT UNINAM(U) DURING STOPCD
DIEUNI::PUSHJ	P,INLMES##	;START THE OUTPUT
	ASCIZ	\Unit = \
	MOVE	T2,.CPACA##	;GET ADDRESS OF AC SET
	MOVE	T2,U(T2)	;GET "U" AT CRASH
	MOVE	T2,UNINAM##(T2)	;GET THE NAME
	PJRST	PRNAME		;PRINT OUT SIXBIT AND RETURN

IFN FTMBTS,<
;ROUTINE TO CALL BUGDMP TO TAKE A CONTINUABLE STOPCD DUMP
;AND THEN SET DF.RQC IN DEBUGF WHICH WILL CAUSE CRSCPY
;TO BE CALLED BY THE BOOT CPU AT THE NEXT TICK.  WE
;CAN'T CALL CRSCPY DIRECTLY BECAUSE THE SCNSER INTERLOCK
;MAY NOT BE FREE.
;ENTER AT FRCCPY TO JUST SET DF.RQC (FROM ADDSDL)
;CALL:	PUSHJ	P,CRSDMP
;	RETURN HERE ALWAYS

CRSDMP:	PUSH	P,JOBSYM##	;KEEP DAEMON FROM THINKING THIS IS A
	SETZM	JOBSYM##	;↑↑RELOAD BY ZEROING THE FLAG THAT IT LOOKS AT
	PUSHJ	P,BUGDMP##	;TAKE DUMP
	  JFCL			;IGNORE ERROR RETURN
	  POP	P,JOBSYM##	;RESTORE SYMBOL TABLE POINTER
FRCCPY::MOVSI	T1,(DF.RQC)	;SET BIT IN DEBUGF WHICH WILL CAUSE
	IORM	T1,DEBUGF##	; CRSCPY TO BE CALLED AT THE NEXT TICK
	POPJ	P,		;RETURN


;ROUTINE TO START UP THE CRASH COPY PROGRAM TO COPY
;A DUMP.
;CALL:	PUSHJ	P,CRSCPY
;	RETURN HERE ALWAYS

CRSCPY::SKIPGE	DEBUGF##	;DON'T DO ANYTHING
	POPJ	P,		; IF DEBUGGING
	PUSHJ	P,FRCSET##	;SETUP TO STORE CHARACTERS IN FRCLIN
	MOVE	T2,CCPNAM##	;GET NAME OF PROGRAM TO RUN
	PUSHJ	P,PRNAME	;STORE NAME
	PJRST	CRLF##		;ADD CRLF AND RETURN
>;END IFN FTMBTS

;CONTINUE TABLE. T1 IS STACK POINTER FOR PROCESS WHICH DID STOPCD.
;CALLED BY XCT CONTAB(CONT)
CONTAB:	JFCL			;(0) .
	JFCL			;(1) .+1
	POP	T1,(T1)		;(2) CPOPJ
	PUSHJ	P,[POP T1,(T1)
		   AOS (T1)
		   POPJ P,]	;(3) CPOPJ1
	JFCL			;(4)
	JFCL			;(5)
	JFCL			;(6)
	JFCL			;(7)
	JFCL			;(10)
	JFCL			;(11)
	JFCL			;(12)
	JFCL			;(13)
	JFCL			;(14)
	JFCL			;(15)
	JFCL			;(16)
	AOS	(T1)		;(17) SPECIAL RETURN
WHATJB:	JUMPLE	J,CPOPJ##	;GET JOB NUMBER
	CAILE	J,JOBMAX##	;RANGE CHECK IT.
	POPJ	P,		;IGNORE IF FUNNY.
	PUSHJ	P,INLMES##	;GIVE THE JOB NUMBER
	ASCIZ	/Job /	; ..
	MOVE	T1,J		; ..
	MOVEM	T1,%SYSJN##
	MOVEM	T1,.CPSJN##
	PUSHJ	P,RADX10	;IN DECIMAL
	PUSHJ	P,INLMES##	;PRINT OUT THE
	ASCIZ	/ on /		; TTY NAME
	MOVE	T2,@TTYTAB##(J)	;GET TTY NAME
	MOVEM	T2,%SYSTN##
	MOVEM	T2,.CPSTN##
	PUSHJ	P,PRNAME	; AND PRINT IT.
	PUSHJ	P,INLMES##	;PRINT OUT
	ASCIZ	/ running /	; THE CUSP NAME
	MOVE	T2,JBTPRG##(J)	; SO OPERATOR
	MOVEM	T2,%SYSPN##
	MOVEM	T2,.CPSPN##
	PUSHJ	P,PRNAME	; CAN FIND HIS JOBS
	PUSHJ	P,INLMES##
	ASCIZ/ User /
	MOVE	T2,JBTPPN##(J)	;GET USER'S PPN
	MOVEM	T2,%SYSPP##	;AND SAVE FOR DAEMON
	MOVEM	T2,.CPSPP##
	PUSHJ	P,PRTPPN##	;PRINT PPN
	JUMPN	S,CRLF##
	PUSHJ	P,INLMES##	;NEW LINE
	ASCIZ	/
UUO is /
	MOVE	T1,.CPTRP##	;PICK UP UUO
	MOVEM	T1,%SYSUU##
	MOVEM	T1,.CPSUU##
	PUSHJ	P,PRTDI8	;PRINT IN OCTAL
	MOVE	T2,.JDAT+JOBPD1## ;GET PC FROM PUSH DOWN LIST
	MOVEM	T2,%SYSUP##
	MOVEM	T2,.CPSUP##
	PUSHJ	P,PCP		;LIST THE LOCATION
	PJRST	CRLF##		;RETURN ON A NEW LINE
SUBTTL	UUO LEVEL ERROR ROUTINES

;INPUT UUO FOR OUTPUT DEVICE
;CALLED AT UUO LEVEL ONLY


ILLINP::JSP	T1,ERRPTU
	ASCIZ	/output /
	PUSHJ	P,ERNAM		;PRINT "DEVICE XXX"
	JSP	T1,UUOMES	;PRINT MESSAGE,UUOPC,STOP JOB
	ASCIZ	/ cannot do input/

;OUTPUT UUO FOR INPUT DEVICE
;CALLED AT UUO LEVEL ONLY


ILLOUT::JSP	T1,ERRPTU
	ASCIZ	/input /
	PUSHJ	P,ERNAM		;PRINT "DEVICE XXX"
	JSP	T1,UUOMES	;PRINT MESSAGE,UUOPC,STOP JOB
	ASCIZ	/ cannot do output/

;ILLEGAL DEVICE DATA MODE (INIT, OPEN, OR SETSTS UUOS)
;CALLED AT UUO LEVEL ONLY


ILLMOD::JSP	T1,ERRPTU
	ASCIZ	/Illegal data mode for /
	JRST	DEVEXC		;PRINT "DEVICE XXX",UUO PC

;IO UUO TO USER CHANNEL WITH NO PREVIOUS INIT OR OPEN
;CALLED AT UUO LEVEL ONLY


IOIERR::JSP	T1,ERRPTU
	ASCIZ	/IO to unassigned channel/
	JRST	UUOPCP		;PRINT UUO PC

;ILLEGAL UUO
;CALLED AT UUO LEVEL ONLY
;SERVES TWO PURPOSES - A) TO WARN WHEN MOVING FROM A LOCATION WITH SPECIAL INSTALLATION
;UUOS TO ONE WITH LACKS THEM
;B) TO WARN OF OLD UUO'S WITH NONSKIP "GOOD" RETURNS WHICH 
;HAVE BEEN "DE-IMPLEMENTED"

UUOERR::EXCH	T1,.UPMP+.UPMUP	;GET UUO PC
	TLNN	T1,USRMOD	;FROM EXEC?
	JRST	EMUERR		;YES
	EXCH	T1,.UPMP+.UPMUP	;PUT THINGS BACK
ILLUUO:	PUSH	P,.UPMP+.UPMUP	;NOW PUSH USER PC ON STACK JUST LIKE UUO
				; (LEAVE STACK UNTOUCHED BEFORE HALT)
				; (START PRESERVES PC FLAGS IN LH)
	PUSHJ	P,GIVRES	;GIVE UP INTERLOCKS
IFN FTPI,<
	SIGNAL	C$IUUO		;SIGNAL ILLEGAL UUO
	  SKIPA			;DOESN'T WANT THE TRAP
	JRST	ERRGOU		;INTERCEPT THE UUO
>	;END FTPI
	JSP	T1,ERRPTU
	ASCIZ	/Illegal UUO/
	MOVE	T2,.UPMP+.UPMUP	;GET UUO PC
	SOJA	T2,PCPNT	;AND PRINT, PRINT USER UUO PC IF DIFF.
;UUO ERROR-MONITOR ERROR AT UUO LEVEL
;CALLED AT UUO LEVEL ONLY

UUOER1::JSP	T1,ERRPTU
	ASCIZ	/UUO error/
	JRST	UUOPCP

;HERE ON AN EXEC MODE UUO ERROR

EMUERR:	EXCH	T1,.UPMP+.UPMUP
	CONSZ	PI,PI.IPA	;AT UUO LEVEL?
	STOPCD	.,STOP,UIL,	;++UUO AT INTERRUPT LEVEL
	STOPCD	.+1,DEBUG,EUE,	;++EXEC UUO ERROR
	MOVE	J,.CPJOB##	;GET JOB NUMBER
	JRST	ILLUUO		;PRINT ERROR MESSAGE
;HERE IF THE USER DIES IN GETWRD OR PUTWRD

UADERR::PUSHJ	P,GIVRES	;RETURN INTERLOCKS
	JSP	T1,ERRPTU
	ASCIZ	/Illegal address in UUO/
	JRST	UUOPCP
;ILLEGAL INSTRUCTION
;HALT INSTRUCTION IS A SPECIAL CASE WHICH STOPS JOB BUT
;THE USER MAY CONTINUE FROM IT(EFFECTIVE ADR.)
;CALLED AT UUO LEVEL WITH A JRST


ILLINS::
IFN FTKL10!FTKS10,<
	LDB	T1,[POINT 9,M,8] ;OPCODE
	CAIL	T1,130		;WITHIN LONG FLOATING POINT RANGE?
	CAILE	T1,177		
	JRST	ILLIN1		;NO, ILLEGAL INSTRUCTION
	MOVSI	T2,(JS.FPS)	;WANT SIMULATION BIT
	SKIPE	[M.FPS##]	;SIMULATION ROUTINE LOADED?
	TDNN	T2,JBTST2##(J)	;AND DOES THE USER WANT SIMULATION?
	CAIA			;NO
	JRST	KALFPS##	;YES, SIMULATE THE KA FP INSTRUCTIONS
IFN FTPI,<
	SIGNAL	C$IUUO		;SIGNAL ILL INSTRS
	  CAIA			;PROGRAM ISN'T INTERESTED
	JRST	ERRGOU		;GO TO THE USER
>
	JSP	T1,ERRPTU	;TELL THE USER TO FIX THE PROGRAM
	ASCIZ	/KA10 floating point instruction/
	JRST	UUOPCP
ILLIN1:>
IFN FTPI,<
	SIGNAL	C$IUUO		;SIGNAL ILL UUO
	  SKIPA			;USER DOESN'T WANT THE TRAP
	JRST	ERRGOU		;GO TO THE USER
>
	HLRZ	T1,M		;ILLEGAL OPCODE
	CAIN	T1,254200	;IS IT A HALT?
	JRST	HALTI		;YES, PRINT DIFFERENT MESSAGE
IFN FTKI10,<
KIIBEG==105
KIIEND==127
	LSH	T1,-9		;MAKE T1=OPCODE
IFN FTKI10,<
	MOVSI	T2,201704	;MASK FOR KL10 INST.
>
	CAIG	T1,KIIEND	;IF TOO LARGE, DON'T SHIFT
	LSH	T2,-KIIBEG+1(T1)	;SHIFT MASK BY OPCODE
	JUMPGE	T2,ILLKAI	;KA10 ILL INST IF SIGN NOT 1
KLONLY:	JSP	T1,ERRPTU
	ASCIZ	/KL10 only instruction/
	JRST	UUOPCP
> ;END FTKI10
ILLKAI:	JSP	T1,ERRPTU
	ASCIZ	/Illegal instruction/
	JRST	UUOPCP		;PRINT UUO PC AND STOP JOB

HALTI:	JSP	T1,ERRPTU
	ASCIZ	/HALT/
	SOS	T2,.JDAT+JOBPD1##	;UUOPC=LOC OF HALT+1
	PUSHJ	P,PCP		;PRINT "USER LOC XXX"
	HRR	M,.UPMP+.UPMUO	;CHKINT CLOBBERS M
	HRRM	M,.JDAT+JOBPD1##	;SAVE EFFECTIVE ADDRESS OF HALT
	PUSH	P,U
	PUSHJ	P,TTYSRC##	;GETTTY
	STOPCD	.,STOP,LNT,	;NONE?!
	JUMPE	U,HALTI2	;JUMP IF JOB DETACHED
	POP	P,U
	PUSHJ	P,TSETBI##	;CLEAR TYPE-AHEAD
	PUSHJ	P,HOLDW##	;START TTY WITH STANDARD RESPONSE,, STOP
				;JOB, LEAVE TTY IN MONITOR MODE
				;DO NOT SET ERROR BIT SO CAN CONTINUE
HALTI1:	PUSH	P,.JDAT+JOBPD1##	;PUT USER RETURN ON END OF PD LIST
	JRST	USRXIT##	;RETURN TO USER IN CASE HE TYPES CONT COMMAND
HALTI2:	POP	P,U
	PUSHJ	P,CRLF##	;HERE TO HANDLE HALT IN DET'D JOB
	PUSHJ	P,ESTOP3##	;STOP JOB WITH CONTINUABILITY
	PUSHJ	P,WSCHED##	;WAIT FOR USER
	JRST	HALTI1		;RESUME NORMAL FLOW

;ILLEGAL TRAP INSTRUCTION
ILLTIN::MOVE	P,[MJOBPD##,,.JDAT+JOBPDL##]
	PUSH	P,.UPMP+.UPMUP
	JSP	T1,ERRPTU
	ASCIZ	/Illegal trap instruction/
	JRST	UUOPCP		;PRINT TRAP INSTR PC AND STOP THE JOB
SUBTTL	I/O ERROR HANDLING ROUTINES

;ROUTINE FOR HUNG IO DEVICE
;CALL	MOVE F,ADDRESS OF DEVICE DATA BLOCK
;	PUSHJ P,DEVHNG


DEVHNG::PUSHJ	P,SVEUF##	;MAKE SURE JOB DATA AREA IS ADDRESSABLE

	PUSHJ	P,CLRACT##	;TURN OFF IO DEVICE ACTIVE BIT IN
				;MEMORY AND S
	LDB	J,PJOBN##	;JOB NUMBER
	JUMPE	J,DEVHN2
IFN FTPI,<
	MOVEI	T1,IR.HNG	;HUNG CONDITION
	TSNN	T1,DEVPSI##(F)	;PROGRAM ENABLED?
	JRST	DEVHN1		;NO
	PUSHJ	P,PSIDVB##	;SIGNAL HUNG DEVICE
	TRO	S,IOIMPM!IOBKTL!IODERR!IODTER ;ALL ERRORS
	PUSHJ	P,SETIOD##	;GET THE JOB GOING
	PJRST	STOIOS##	;STORE BITS AND RETURN
>
DEVHN1:	MOVSI	T1,JERR		;FLAG SO USER DOESN'T
	IORM	T1,JBTSTS(J)	;GET IF TRAP ENABLED
DVHN1A:	IFN	FTMP,<
	CPLOCK	(SCD)		;GET SCHEDULAR LOCK
>
	MOVEI	T1,STOPQ##
	DPB	T1,PJBSTS##
	PUSHJ	P,ANYCPU##	;IS HE RUNNING ANYWHERE NOW?
	  SKIPA			;YES MUST DELAY HANGING HIM
	JRST	DVHN1C		;NO, CAN STOP HIM NOW
	MOVEI	T2,1		;GET A WORRD
	PUSHJ	P,GETWDS##	;OF FREE CORE
	  JRST	DVHN1C		;FAILED BLAST JOB ANYWAY
	MOVEM	F,(T1)
	HRLM	J,(T1)		;SAVE J
	MOVE	T2,.CPCPN##
	DPB	T2,[POINT 3,T1,3] ;CPU IS US
	TLO	T1,400000
	MOVEI	T2,1		;IN A TIC
	HRLI	T2,DVHN1B
	SYSPIF
	IDPB	T2,CLOCK##
	IDPB	T1,CLOCK##
	SETOM	CLKNEW##
	SYSPIN
IFN	FTMP,<
	CPUNLK	(SCD)
>
	POPJ	P,		;AND RETURN FOR NOW
DVHN1B:	HLRZ	J,(T1)		;RESTORE J
	HRRZ	F,(T1)		;AND F
	MOVEI	T2,(T1)		;RETURN FREE CORE
	MOVEI	T1,1
	PUSHJ	P,GIVWDS##
	PUSHJ	P,SVEUB##	;MAKE JOB ADDRESSABLE
	JRST	DVHN1A		;CHECK TO SEE IF HE'S STILL HERE
DVHN1C:	PUSH	P,F		;GIVRSC CLOBBERS F
	PUSHJ	P,GIVRSC	;RETURN RESOURCES, COULD HAVE SOME, IF STR YANKED
	POP	P,F
	MOVEI	T1,STOPQ##
	DPB	T1,PJBSTS##
IFN	FTMP,<
	CPUNLK	(SCD)
>
DEVHN2:	JSP	T1,ERRDEV
	ASCIZ	/Hung /
	JRST	DEVEXC

;BAD DECTAPE DIRECTORY
;CALLED AT INTERRUPT AND UUO LEVELS WITH F AND J SETUP

BADDIR::PUSHJ	P,SVEUF##	;MAKE JOB DATA AREA ADDRESSABLE

	JSP	T1,ERRPNT
	ASCIZ	/Bad directory for /
	
;ROUTINE TO PRINT "DEVICE XXX; EXEC CALLED FOR EXEC/USER YYY"
;THEN STOP JOB
;TO BE USED BY DEVICE DEPENDENT ERROR MESSAGES AFTER JSP T1,DEVERR


DEVEXC::PUSHJ	P,ERNAM		;PRINT "DEVICE XXX"
	SKIPE	JBTADR##(J)	;CHECK FOR JOB IN CORE
	JRST	EXCALP		;PRINT "EXEC CALLED FROM EXEC/USER LOC YYY"
	JRST	PCSTOP		;JUST STOP THE JOB


;ROUTINE TO HALT A JOB WHEN A DEVICE IS NOT READY FOR I/O
;CALLED FROM XXXSER AT UUO LEVEL
;CALL	MOVE F,ADDR. OF DEV. DDB
;	PUSHJ P,HNGSTP
;WILL DISPATCH TO USER'S AREA IF JOBINT IS NON-0


HNGSTP::PUSH	P,M
	PUSHJ	P,HNGSTX
	PJRST	MPOPJ##
HNGSTX:	PUSHJ	P,SAVE3##	;SAVE P1-P3	
	SKIPE	P3,DEVEVM(F)	;DOES DEVICE HAVE EVM?
	SETO	P3,		;NO
	PUSHJ	P,RTNEVM##	;RETURN ANY EVM DEVICE HAS FOR I/O
				; P3=-1 IF DEVICE HAD NO EVM, 0 IF IT DID
	SOS	.JDAT+JOBPD1##	;BACK UP PC
	MOVEI	T4,.ERIDV	;DEV OR INTERCEPT
IFN FTPI,<
	TLO	M,(1B0)
	PUSHJ	P,PSIJBI##	;CALL PSISER
	  PJSP	P1,HNGST1	;P1 NON-ZERO TO INDICATE INTERCEPTING
	TLZ	M,(1B0)
>
	SETO	T2,		;MAKE T2 NON-ZERO SO LATER CHECKS WILL WORK
	LDB	T3,PJOBN##
	SKIPE	T3,JBTSTS##(T3)
	TRNN	T3,JS.ASA
	PUSHJ	P,CHKINT	;SEE IF SET UP
	  SETZB	T2,T3		;NO
	MOVE	P1,T2		;SAVE LOCATION
	PUSHJ	P,DOINT		;PREPARE INTERCEPT
	JUMPN	T2,HNGST1	;IF NOT INTERCEPTING
	PUSHJ	P,INCPD1##
HNGST1:	JUMPL	T3,HNGST3	;YES, DOES HE WANT THE ERROR MESSAGE?
	PUSH	P,J		;YES
	PUSH	P,W
	PUSH	P,S
	PUSH	P,U
	PUSH	P,F		;SAVE DEV'S S WORD & DDB
	LDB	J,PJOBN##	;GET JOB NUMBER
	PUSHJ	P,FNDPDS##	;FIND PDB AND PUT IT'S ADDRESS IN W
				; IF NONE HALT.
	EXCH	F,0(P)		;GET F FROM DEVICE
	LDB	T1,PDVSTA##	;GET JOB'S LOCATION
	EXCH	F,0(P)		;GET F FOR TTY BACK
	JUMPE	T1,HNGST2	;CENTRAL SITE IF 0 (DISK)
IFN FTNET,<
	PUSHJ	P,STBOPR##	;GET OPR LINE
>
IFE FTNET,<
	MOVE	U,OPRLDB##
	LDB	T1,LDPLNO##
>
	SKIPA	U,LINTAB##(T1)	;GET LDB ADDR
HNGST2:	MOVE	U,OPRLDB##	;CENTRAL STA OPR
	PUSHJ	P,INLMES##	;OUTPUT START OF MESSAGE
	ASCIZ	/
%ππProblem on /
	PUSHJ	P,ERNAM		;PRINT PHYSICAL DEVICE NAME (USING -1(P))
	PUSHJ	P,INLMES##	;LOGICAL DEVICE OPR
	ASCIZ	/ for job /
	PUSHJ	P,PJOB##
	PUSHJ	P,CRLF##
	PUSHJ	P,TTYFUW##	;FIND CURRENT JOB'S TTY
	PUSHJ	P,CRLF##	;START A NEW LINE
	PUSHJ	P,ERNAM		;PRINT "DEVICE XXX"
	PUSHJ	P,INLMES##	;AND MSG.
	ASCIZ	/, OPR/
IFN FTNET,<
	EXCH	F,(P)		;GET POINTER DDB
	LDB	T1,PDVSTA##	;GET DEVICES LOCATION
	EXCH	F,(P)
	PUSHJ	P,CVTSBT##	;CONVERT TO SIXBIT
	MOVE	T2,T1		;GET SIXBIT FOR PRNAME
	PUSHJ	P,PRNAME	;AND PRINT IT
>
	PUSHJ	P,INLMES##
	ASCIZ	/ action requested/

	MOVEI	T1,TTYSTR##	;UNLESS ERROR INTERCEPTING
	SKIPN	P1		;CALL HOLD0 (STOP JOB,START TTY)
HNGST8:	MOVEI	T1,HNGST4	;SET UP ROUTINE TO CALL
	PUSHJ	P,(T1)		;START TTY TYPING ERR MESSAGE
				; LEAVE IN COMMAND MODE
				;DO NOT SET JOB ERROR SO CAN CONTINUE
	POP	P,F		;BRING BACK DEV DDB & S WORD
	POP	P,U
	POP	P,S
	POP	P,W
	POP	P,J
	JUMPN	P1,HNGST3	;DO INTERCEPT IF WANTED
	PUSHJ	P,WSCHED##	;RESCHEDULE
	MOVSI	T1,DVDSK	;GET BIT TO TEST
	TDNN	T1,DEVMOD(F)	;IS THIS A DISK?
	 JRST	HNGST9		;NO, SKIP THIS
	PUSHJ	P,CHEKU##	;YES, WAS F/S YANKED?
	 PJRST	DEVHNG		;YES, SAY IT'S HUNG
HNGST9:	AOJN	P3,CPOPJ##	;DEVICE HAVE EVM WHEN THE ERROR OCCURRED?
	MOVE	M,-5(P)		;RESTORE M FOR ADDRESS CHECK
	PJRST	RSTEVM##	;YES, RESTORM EVM FOR I/O
HNGST3:	MOVEI	T1,DEPOND!DEPIND	;NON-BLOCKING I/O NOT DONE BITS
	ANDCAM	T1,DEVAIO(F)	;CLEAR THEM SO THAT IN/OUT UUOS WILL WIN
	MOVEI	P1,1(M)		;SAVE 1(INTERCEPT LOC)
	LDB	T1,PIOMOD##	;MODE
	MOVE	T4,DEVADV(F)
	TLNN	T4,DEPADV
	CAIL	T1,SD		;DUMP?
	JRST	HNGST7		;YES, NO BUFFERS TO FIX
	HRR	M,DEVBUF(F)	;BUFFERED, FIX UP BUFFER HDR
	TLNE	S,IO		; SO REPEATING THE UUO WILL WIN
	HLR	M,DEVBUF(F)	; (THEY WERE ALREADY ADVANCED)
	HRRZ	T4,M		;SAVE LOCATION OF THE HDR
	JUMPE	T4,HNGST7	;JUMP IF NO BUFFERS YET SET UP
	PUSHJ	P,GETWRD##	;GET LOCATION OF FIRST BUFFER
	JRST	HNGST7		;ADDRESS CHECK - CAN'T FIX THE RING
	MOVE	P2,T1		;P2=ADDRESS OF FIRST BUFFER
	MOVEI	T3,10000	;END OF LOOP INSURANCE
HNGST5:	HRR	M,T1		;M=ADDRESS OF THIS BUFFER
	PUSHJ	P,GETWRD##	;GET THE ADDRESS OF THE NEXT ONE
	  JRST	HNGST7		;ADDRESS CHECK, FORGET IT
	CAIE	P2,(T1)		;THE ONE WE WANT?
	SOJGE	T3,HNGST5	;NO, STEP TO NEXT
	JUMPL	T3,HNGST7	;YES, JUMP IF RING WAS NOT CLOSED
	HRR	P2,M		;P2=POINTER TO NEXT BUFFER
	TLO	T1,IOUSE	;INDICATE "FULL" FOR TEST AT INPUT
	PUSHJ	P,PUTWDU##	;STORE THAT
	HRR	M,T4		;RESTORE HEADER ADDRESS
	MOVE	T1,P2		;T1=DEADVANCED BUFFER POINTER
	PUSHJ	P,PUTWDU##	;STORE THAT IN THE HDR
HNGST7:	HRRI	M,(P1)		;M=ADDRESS OF THIRD WORD OF INT. BLOCK
	PUSHJ	P,GETWDU##	;FETCH IT
	HLR	T1,.UPMP+.UPCTA
	SKIPL	M		;SKIP IF PSISER TRAP
	PUSHJ	P,PUTWDU##	;STORE FOR INTERRUPT ROUTINE
QKUSXT::
ERRGOU::HRRI	P,.JDAT+JOBPD1## ;SET P FOR NORMAL EXIT
				;(POP P,UUO0 ; JRST @UUO0)
	SETZB	F,.CPISF##	;NO LONGER AT SCHEDULER LEVEL
	SETZM	.CPSCF##	;CLEAR FORCED RESCHEDULE FLAG
	NTGIVE			;RETURN NETWORK INTERLOCK
	PJRST	USRXIT##	;LET UUOCON RETURN TO USER
HNGST4:IFN	FTJCON,<
	MOVEI	T1,JDCON	;NO ERROR INTERCEPT
	IORM	T1,JBTSTS##(J)	; SO SET DEV CONT BIT
>
	PUSHJ	P,CRLF##	;PRINT A CRLF
	PUSH	P,TTYTAB##(J)	;MAKE THIS JOB LOOK DETACHED
	SETZM	TTYTAB##(J)	; SO IT'S TERMINAL IS NOT PUT
				; AT COMMAND LEVEL.
	PUSHJ	P,STOP1C##	;STOP JOB-SETUP TO RESCHEDULE
				; BUT DO NOT CALL WSYNC
	POP	P,TTYTAB##(J)	;ALL TTYSRC TO WIN AGAIN
	POPJ	P,0		;RETURN
;CHKINT -- ROUTINE TO SETUP FOR JOBINT USAGE
;CALL:	MOVEI	T4,ERROR TYPE (CLASS)
;	PUSHJ	P,,CHKINT
;SKIP RETURNS	M = RELATIVE BLOCK ADDRESS+2 (WHERE OLD PC IS STORED)
;		T1 = NEW PC
;		T3 = CONTENTS OF BITS,,CLASS
;STORES ERROR TYPE IN BLOCK+3.

IFN FTCCIN!FTDAEM,<
CHKINT::SKIPN	JBTADR##(J)	;JOB HAVE CORE?
	POPJ	P,		;NO - THEN NO JOBINT
	MOVE	T1,JBTSTS##(J)	;JOB STATUS
	TLNN	T1,SWP		;IS JOB SWAPPED OR
	TRNE	T1,JS.ASA	;EXEC MODE UUO IN PROGRESS?
	POPJ	P,		;YES, DON'T TRAP
	HRR	M,.JDAT+JOBINT##  ;GET ERROR LOCATION
				; SET M FOR GETWRD/PUTWRD
	HRRZ	T1,M		;CHECK FIRST WORD OF INTERRUPT VECTOR
	PUSHJ	P,FLTST##	;IN-CORE?
	  POPJ	P,		;NO
	ADDI	T1,3		;LAST WORD OF VECTOR
	PUSHJ	P,FLTST##	;IN-CORE?
	  POPJ	P,		;NO
	TRNE	M,-1		;NO INTERRUPT IF JOBINT NOT SET
	PUSHJ	P,GETWRD##	;GET NEW PC
	  POPJ	P,		;ADDRESS CHECK - GIVE UP
	HRL	T4,T1		;SAVE NEW PC
	PUSHJ	P,GETWR1##	;GET BITS,,CLASS
	  POPJ	P,		;OUT OF BOUNDS
	MOVE	T3,T1		;SAVE THOSE
	PUSHJ	P,GETWR1##	;GET OLD PC
	  POPJ	P,		;ADDRESS CHECK - GIVE UP
	TRNE	T4,-1		;IF SPECIAL,
	TRNE	T3,(T4)		;  SEE IF USER OMITTED IT
	SKIPE	T1		;SEE IF IN USE ALREADY
	POPJ	P,		;YES - GIVE UP
	PUSHJ	P,GETWR1##	;GET THE OLD WORD
	  POPJ	P,0		; ADDRESS CHECK
	TLO	T1,(T4)		;TURN ON THE NEW BIT
	PUSHJ	P,PUTWRD##	;  STORE ERROR BITS
	  POPJ	P,		;ADDRESS CHECK - GIVE UP
	HLRZ	T1,T4		;GET NEW PC
	JUMPE	T1,CPOPJ##	;GIVE UP IF JUNK
	SOJA	M,CPOPJ1##	;OK RETURN

;DOINT -- ROUTINE TO PERFORM THE JOBINT
;CALL:	MOVE	T1,NEW PC
;	MOVEI	M,USER VIRTUAL ADDRESS OF INTERRUPT BLOCK + 2
;RETURN WITH JOBPD1 UPDATED

DOINT::	JUMPE	T2,CPOPJ##	;IF NO BLOCKS, GIVE UP
	EXCH	T1,.JDAT+JOBPD1##	;STORE NEW PC
	TLO	T1,(XC.USR)	;MAKE SURE USER MODE IS ON
	HLLM	T1,.JDAT+JOBPD1##	;STORE FLAGS
	PJRST	PUTWDU##	;STORE OLD PC AND RETURN
>;END IFN FTCCIN!FTDAEM

;ROUTINE TO PRINT "SWAP READ ERROR"
;CALLED FROM SWAPPER AT CLOCK LEVEL (USUALLY)
;CALL:	MOVE J,JOB NUMBER
;	PUSHJ P,ERRSWP
;	ALWAYS RETURN TO SWAPPER


ERRSWP::PUSHJ	P,SVEUB##	;LOAD UBR
	MOVSI	T1,JERR		;SET JERR SO WE DO NOT
	IORM	T1,JBTSTS##(J)	;TRY TO INTERCEPT
	JSP	T1,ERRPNT	;PRINT MESSAGE
	ASCIZ	/Swap read error/
	PJRST	PCSTOP		;START TTY AND SET JERR BIT SO
				; JOB CANNOT CONTINUE. PI 7 WILL NOT
				; BE REQUESTED SINCE SWAPPING JOB CANNOT
				; BE CURRENT JOB.
				;ERRPNT PUSHED TWO AC'S. PCSTOP REMOVES THEM

SUBTTL	COMMON ERROR MESSAGE ROUTINES

;COMMON ERROR MESSAGE SETUP ROUTINES
;CALL:	JSP T1,ERRPTU, ERRDEV, OR ERRPNT
;	ASCIZ /message/
;	RETURNS HERE WITH F SAVED 0(P)
;	C(F)=TTYDDB, U TO TTY OUTPUT BUFFER POINTER
;	J=JOB NUMBER, W=ADDR OF PDB

;USE ERRPTU IF AT UUO LEVEL FOR SURE
;ERRDEV IF ERROR FOR AN ASSIGNED DEVICE AT ANY LEVEL
;ERRPNT WITH J ALREADY SET TO OFFENDING JOB NUMBER
;THE JSP CALL IS USED IN CASE PUSHDOWN SPACE BECOMES CRITICAL
;AGAIN AND ERRPNT HAS TO WIPE EXISTING LIST OUT


ERRPTU::SKIPA	J,.CPJOB##		;BLAME CURRENT JOB IF NOT 0.
ERRDEV::LDB	J,PJOBN##		;JOB NO. FROM DEVICE DATA BLOCK
ERRPNT::PUSHJ	P,FNDPDB##	;FIND PDB FOR THIS JOB
	  HRRZ	W,JBTPDB##	;USE NULL JOB'S PDB
	SKIPN	J		;ERROR IN NULL JOB?
	SETOM	.CPNJE##	;YES, SET FLAG FOR ERROR IN NULL JOB
				; SO STATE OF NULL JOB WILL BE REESTABLISHED
				; WHEN IS IT RUN AGAIN(SEE CLOCK1)

	CAILE	J,JBTMAX##	;JOB NUMBER OR SEGMENT NUMBER
	STOPCD	.,STOP,SOR,	;++SEG OUT OF RANGE


	PUSH	P,U		;SAVE CALL TO ERROR(JSP U,ERROR)
	PUSH	P,F		;SAVE ADR. OF DEV. DATA BLOCK
	PUSH	P,T1		;SAVE RETURN FROM ERRPNT
	MOVE	T1,JBTSTS##(J)
	TDNE	T1,[JERR,,JS.ASA]
	JRST	ERRPT1
IFN FTPI,<
	PUSHJ	P,USREIJ##	;SIGNAL USER ERROR
	JRST	ERRGOU
>
IFN FTCCIN!FTDAEM,<
	MOVEI	T4,.EREIJ	;DOES THIS JOB WANT
	PUSHJ	P,CHKINT	; TRAP ALL ERRORS?
	  JRST	ERRPT1		;NO--BOMB HIM OUT
	JUMPGE	T3,ERRPT1	;JUMP IF HE WANTS MESSAGE
	MOVE	T2,M		;NO MESSAGE
	PUSHJ	P,DOINT		;PREPARE INTERCEPT
;***NEED TO STORE ERROR CODE***
	PJRST	QKUSXT		;BACK TO USER
>
ERRPT1:	PUSHJ	P,TTYERP##	;FIND TTY FOR THIS ERROR (VIA J)
	  PUSHJ	P,ERINDJ	;ERROR IN DETACHED JOB
	PUSHJ	P,INLMES##
	ASCIZ	/?
/
	PUSHJ	P,PRQM##	;PRINT QUESTION MARK ON NEXT LINE
				; FOR BATCH AND SCRIPT
	PJRST	INLMES##	;PRINT MESSAGE SPECIFIED BY CALLER
				; AND RETURN TO LOC. AFTER MESSAGE

ERINDJ::JUMPE	J,ERINNJ	;JUMP IF NULL JOB
	PUSHJ	P,INLMES##	;PRINT ERROR MESSAGE
	ASCIZ	/?Error in detached job/
	PUSHJ	P,PRJBNM	;PRINT JOB # AND PROGRAM NAME
	PJRST	CRLF##		;PRINT <CRLF> AND RETURN
ERINNJ:	PUSHJ	P,INLMESS##	;PRINT ERROR MESSAGE
	ASCIZ	/?Error in job 0 (null job)
/
	POPJ	P,
;ROUTINE TO PRINT UUO PC AND STOP JOB
;IF IN USER MODE PC WILL PRINT AS "AT USER LOC XXX"
;IF IN EXEC MODE "AT EXEC LOC XXX; EXEC CALLED FORM EXEC/USER/ LOC YYY


UUOMES::PUSHJ	P,CONMES##	;PRINT MESSAGE POINTED TO BY T1
UUOPCP::MOVE	T2,.JDAT+JOBPD1##	;UUO PC STORED IN JOB DATA AREA
				; FIRST LOC ON PD LIST
	SOJA	T2,PCPNT	;DECREMENT TO POINT TO UUO IN USER AREA

;ROUTINE TO PRINT ONE OF THREE MESSAGES AND STOP JOB
;1) "AT EXEC LOC XXX; EXEC CALLED FROM EXEC LOC YYY"
;2) "AT EXEC LOC XXX; EXEC CALLED FORM USER LOC YYY"
;3) "AT USER LOC YYY"

;CALL:	MOVE T2, XXX		;WITH PC FLAGS IN LH
;	PUSHJ P,PCPNT
;	NEVER RETURN IF AT UUO LEVEL


PCPNT::IFN FTWATCH,<
	TLNE	T2,USRMOD	;MAKE SURE CONTROL-T
	HRRM	T2,JBTPC##(J)	; GIVES CORRECT ANSWER
>
	PUSHJ	P,PCP		;PRINT " AT EXEC XXX" OR " AT USER "
	TLNE	T2,USRMOD	;WAS PC IN USER MODE?
	JRST	PCSTOP		;YES, ENOUGH INFO.

;ROUTINE TO PRINT "; UUO AT [EXEC or USER] PC XXXXXX" AND STOP JOB
;CALL:	PUSHJ P,EXCALP
;	NEVER RETURNS IF AT UUO LEVEL
EXCALP::PUSHJ	P,INLMES##
	ASCIZ	/; UUO/
	MOVE	T2,.JDAT+JOBPD1##	;UUO PC IN JOB DATA AREA
	SUBI	T2,1		;BACK IT UP TO POINT TO UUO
	PUSHJ	P,PCP		;PRINT "EXEC LOC " OF USER LOC
PCSTOP::PUSH	P,U
	JUMPN	J,PCSTP5	;NULL JOB?
	PUSHJ	P,TTYERP	;YES--FIND THE OPR
	  JRST	PCSTP6		;WE HAVE A VALID LINE
	STOPCD	.,STOP,NJT,	;NULL JOB HAS TTY
PCSTP5:	PUSHJ	P,TTYSRC##	;SET TTY
	STOPCD	.,STOP,LN1,	;NONE?!
	JUMPE	U,PCSTP2	;IS IT DETACHED?
PCSTP6:	SKIPE	T1,F		;SKIP IF NO DDB
	LDB	T1,PJOBN##	;GET JOB #
	CAMN	T1,J		;IS THIS THE TTY OF THE LOOSER
	PUSHJ	P,TSETBI##	;CLEAR TYPE-AHEAD
PCSTP2:
IFN FTPI!FTCCIN!FTDAEM,<
	MOVE	T1,JBTSTS##(J)	;GET JOB STATUS
	TDNE	T1,[JERR,,JS.ASA]	;CAN WE INTERCEPT
	JRST	PCSTP1		;NO--STOP JOB
>
IFN FTPI,<
	PUSHJ	P,PSIERR##
	  JRST	PCSTP4		;AT CLOCK LEVEL, CATCH IT AT CIPXIT
	  JRST	ERRGOU		;AT UUO LEVEL, CATCH IT AT USRXIT
>
IFN FTCCIN!FTDAEM,<
	MOVEI	T4,.EREIJ	;DOES THIS JOB WANT
	CAMN	J,.CPJOB##	;CANT INTERCEPT IF ON CLOCK LEVEL
	PUSHJ	P,CHKINT	; TRAP ALL ERRORS?
	  JRST	PCSTP1
	PUSHJ	P,DOINT		;PREPARE INTERCEPT
	PJRST	QKUSXT		;BACK TO USER
>
PCSTP1:	JUMPN	U,PCSTP3	;IS JOB DET'D
	POP	P,U
	PUSHJ	P,CRLF##	;YES,
	PUSHJ	P,ESTOP##	;STOP JOB
	JRST	ECONT		;RESUME FLOW
PCSTP3:	PUSHJ	P,HOLD##	;STOP JOB SET ERROR BIT
PCSTP4:	POP	P,U
;HERE TO CONTINUE AFTER ERROR (IF AT PI LEVEL OR USER TYPES CONT)
ECONT:	POP	P,F		;RETURN ONLY IF AT INTERRUPT LEVEL
	JRST	TPOPJ##		;REMOVE ERROR CALL AND RETURN
				;ALTHOUGH U WAS PUSHED, POP INTO T1, PERSERVE LINE NUMBER

;ROUTINE TO TYPE A NUMBER AS HALFWORDS SEPARATED BY COMMAS.
;CALL:	MOVE	T1,NUMBER
;	PUSHJ	P,HWDPNT
;	RETURN

HWDPNT::PUSH	P,T1		;SAVE T1 FOR RH
	HLRZS	T1		;KEEP JUST LH
	PUSHJ	P,OCTPNT	;PRINT AS 6 OCTAL DIGITS
	PUSHJ	P,INLMES	;PRINT THE TWO COMMAS
	ASCIZ/,,/		;...
	POP	P,T1		;RESTORE T1 FOR RH
	PJRST	OCTPNT		;PRINT RH AND RETURN


;ROUTINE TO PRINT PC AS:
;1) "EXEC PC XXX" OR "USER PC XXX"
;CALL:	MOVE T2,PC TO PRINT(LH=PC FLAGS)
;	PUSHJ P,PCP


XMODE:	ASCIZ	/ at exec PC /
UMODE:	ASCIZ	/ at user PC /

PCP::	MOVEI	T1,XMODE	;ASSUME PC IN EXEC MODE
	TLNE	T2,USRMOD	;IS IT?
PCPU::	MOVEI	T1,UMODE	;NO, USER MODE
	PUSHJ	P,CONMES##	;PRINT ONE OR OTHER
	HRRZ	T1,T2		;PRINT RIGHT HALF IN OCTAL
				; FALL INTO OCTPNT


;ROUTINE TO PRINT 6 DIGIT OCTAL NUMBER
;CALL:	MOVEI LINE,LINE DATA BLOCK ADDRESS FOR TTY
;	HRR T1, OCTAL NUMBER
;	PUSHJ P,OCTPNT
;	RETURN T2,PRESERVED,T1 DESTROYED

OCTPNT::HRLZ	T1,T1		;MOVE TO LH FOR ROTATING
	TRO	T1,700000	;SETUP AN END FLAG

OCTP1:	ROT	T1,3		;GET NEXT OCTAL DIGIT
	TLNN	T1,777777	;WAS THAT FLAG?
	POPJ	P,		;YES, DO NOT PRINT IT
	PUSH	P,T1		;SAVE T1 OVER I/O ROUTINE
	PUSHJ	P,PRTNUM	;NO, PRINT OCTAL DIGIT
	POP	P,T1		;RESTORE T1
	HRRI	T1,0		;CLEAR RH
	JRST	OCTP1		;GET NEXT OCTAL DIGIT
;ROUTINE TO ADD 1 TO T1 AND PRINT DECIMAL
;SAME CALL AS OCTPNT

DECP1::	AOJA	T1,RADX10	;ADD 1 AND GO PRINT

;ROUTINE TO PRINT DECIMAL
;CALL:	SAME AS OCTPNT
;T2:	PRESERVED

RADX10::PUSH	P,T2		;SAVE T2
	PUSHJ	P,PRTDIG	;PRINT DECIMAL DIGITS
	PJRST	T2POPJ##	;RESTORE T2 AND RETURN

;RECURSIVE DECIMAL PRINT ROUTINE
;CALL:	MOVE T1,DECIMAL NO.
;	PUSHJ P,PRTDIG

PRTDIG::IDIVI	T1,12		;DIVIDE BY 10
	HRLM	T2,(P)		;RT ON PD LIST
	JUMPE	T1,.+2		;FINISHED?
	PUSHJ	P,PRTDIG	;NO, CALL S OR F 
PRTNMM:	HLRZ	T1,(P)		;YES, GET LAST NUMBER
PRTNUM:	MOVEI	T3,"0"(T1)	;CONVERT TO ASCII
	PJRST	COMTYO##	;AND TYPE IT OUT

;RECURSIVE OCTAL PRINT ROUTINE
;CALL:	SAME AS PRTDIG

PRTDI8::IDIVI	T1,10		;DIVIDE BY 8
	HRLM	T2,(P)		;PUT ON STACK
	JUMPE	T1,PRTNMM	;FINISHED?
	PUSHJ	P,PRTDI8	;NO - LOOP
	PJRST	PRTNMM		;OUTPUT

;SUBROUTINE TO PRINT 22 BIT OCTAL ADDRESS
;CALL:	MOVE	T1,22 BIT ADDRESS
;	PUSHJ	P,PRT22A
;	ALWAYS RETURN

PRT22A::PUSH	P,T1		;SAVE 22 BIT ADDRESS
	HLRZ	T1,(P)		;GET HIGH ORDER HALF
	JUMPE	T1,PRT22B	;IS IT 0 (USUALLY EXCEPT BIG SYSTEMS)
	PUSHJ	P,PRTDI8	;NO, PRINT AS LEADING 0 SUPPRESSED OCTAL
PRT22B:	POP	P,T1		;GET LOW ORDER HALF
	PJRST	OCTPNT		;PRINT AS NON ZERO SUPPRESSED OCTAL (RH ONLY)

;ROUTINE TO PRINT "DEVICE XXX"
;CALL	MOVE U,ASCII OUTPUT BYTE POINTER
;	PUSH P,F
;	PUSHJ P,ERNAM


ERNAM::	PUSHJ	P,INLMES##
	ASCIZ	/device /
	SKIPN	T2,-1(P)	;IS F = 0?
	PJRST	PRNAM1		;YES, MESSAGE WITHOUT NAME
	MOVSI	T1,DVDSK	;DEVICE IS DISK BIT
	TDNN	T1,DEVMOD(T2)	;SKIP IF DISK
	JRST	ERNAM1		;NOT DISK, GET PHYSICAL DEVICE NAME
	SKIPN	T1,DEVUNI##(T2)	;GET CURRENT UNIT DATA BLOCK ADDRESS
	SKIPE	T1,DEVFUN##(T2)	;IF UNIT REMOVED, GET SAVED ADDRESS
	SKIPA	T2,UNINAM##(T1)	;GET PHYSICAL UNIT NAME AND SKIP TO PRNAM1
ERNAM1:	MOVE	T2,DEVNAM(T2)	;NO, GET DEVICE NAME


;ROUTINE TO PRINT SIXBIT NAME
;CALL	MOVE U,ASCII OUTPUT BYTE POINTER
;	MOVE T2,NAME
;	PUSHJ P,PRNAME


PRNAM1:	MOVEI	T1,0
	LSHC	T1,6		;SHIFT IN NEXT CHAR.
	MOVEI	T3,40(T1)	;ASCII VERSION INTO CHREC FOR OUTCHS
	PUSHJ	P,COMTYO##	;OUTPUT CHARACTER
PRNAME::JUMPE	T2,CPOPJ##
	JRST	PRNAM1


;ROUTINE TO PRINT SIXBIT WORD WITH TRAILING SPACES
;CALL:	SAME AS PRNAME.
PRSIXB::MOVEI	T3,6
	PUSH	P,T3
PRSIX0:	SETZ	T3,
	ROTC	T2,6
	ADDI	T3,40
	PUSHJ	P,COMTYO##
	SOSLE	(P)	
	  JRST	PRSIX0
	JRST	T3POPJ##


	LIT

ERREND:	END